From a63ce5a37c9655f4f453d848285b85fb91625390 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 28 Sep 2023 13:29:04 +0200 Subject: [PATCH] elf: allocate .tdata and .tbss sections --- src/link/Elf.zig | 66 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 10 deletions(-) diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 30eb1deb46..8979932f61 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -46,7 +46,9 @@ phdr_load_zerofill_index: ?u16 = null, /// The index into the program headers of the PT_TLS program header. phdr_tls_index: ?u16 = null, /// The index into the program headers of a PT_LOAD program header with TLS data. -phdr_load_tls_index: ?u16 = null, +phdr_load_tls_data_index: ?u16 = null, +/// The index into the program headers of a PT_LOAD program header with TLS zerofill data. +phdr_load_tls_zerofill_index: ?u16 = null, entry_addr: ?u64 = null, page_size: u32, @@ -499,7 +501,7 @@ pub fn allocateAllocSection(self: *Elf, opts: AllocateAllocSectionOpts) error{Ou .sh_flags = opts.flags, .sh_addr = phdr.p_vaddr, .sh_offset = phdr.p_offset, - .sh_size = phdr.p_filesz, + .sh_size = phdr.p_memsz, .sh_link = 0, .sh_info = 0, .sh_addralign = opts.alignment, @@ -631,24 +633,37 @@ pub fn populateMissingMetadata(self: *Elf) !void { } if (!self.base.options.single_threaded) { - if (self.phdr_load_tls_index == null) { + if (self.phdr_load_tls_data_index == null) { const alignment = if (is_linux) self.page_size else @as(u16, ptr_size); - self.phdr_load_tls_index = try self.allocateSegment(.{ + self.phdr_load_tls_data_index = try self.allocateSegment(.{ .size = 1024, .alignment = alignment, .flags = elf.PF_R | elf.PF_W, }); } + if (self.phdr_load_tls_zerofill_index == null) { + const alignment = if (is_linux) self.page_size else @as(u16, ptr_size); + self.phdr_load_tls_zerofill_index = try self.allocateSegment(.{ + .size = 0, + .alignment = alignment, + .flags = elf.PF_R | elf.PF_W, + }); + const phdr = &self.phdrs.items[self.phdr_load_tls_zerofill_index.?]; + phdr.p_offset = self.phdrs.items[self.phdr_load_tls_data_index.?].p_offset; // .tbss overlaps .tdata + phdr.p_memsz = 1024; + } + if (self.phdr_tls_index == null) { - const phdr = &self.phdrs.items[self.phdr_load_tls_index.?]; + const phdr_tdata = &self.phdrs.items[self.phdr_load_tls_data_index.?]; + const phdr_tbss = &self.phdrs.items[self.phdr_load_tls_zerofill_index.?]; try self.phdrs.append(gpa, .{ .p_type = elf.PT_TLS, - .p_offset = phdr.p_offset, - .p_vaddr = phdr.p_vaddr, - .p_paddr = phdr.p_paddr, - .p_filesz = phdr.p_filesz, - .p_memsz = phdr.p_memsz, + .p_offset = phdr_tdata.p_offset, + .p_vaddr = phdr_tdata.p_vaddr, + .p_paddr = phdr_tdata.p_paddr, + .p_filesz = phdr_tdata.p_filesz, + .p_memsz = phdr_tbss.p_vaddr + phdr_tbss.p_memsz - phdr_tdata.p_vaddr, .p_align = ptr_size, .p_flags = elf.PF_R, }); @@ -724,6 +739,31 @@ pub fn populateMissingMetadata(self: *Elf) !void { try self.last_atom_and_free_list_table.putNoClobber(gpa, self.bss_section_index.?, .{}); } + if (self.phdr_load_tls_data_index) |phdr_index| { + if (self.tdata_section_index == null) { + self.tdata_section_index = try self.allocateAllocSection(.{ + .name = ".tdata", + .phdr_index = phdr_index, + .alignment = ptr_size, + .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS, + }); + try self.last_atom_and_free_list_table.putNoClobber(gpa, self.tdata_section_index.?, .{}); + } + } + + if (self.phdr_load_tls_zerofill_index) |phdr_index| { + if (self.tbss_section_index == null) { + self.tbss_section_index = try self.allocateAllocSection(.{ + .name = ".tbss", + .phdr_index = phdr_index, + .alignment = ptr_size, + .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS, + .type = elf.SHT_NOBITS, + }); + try self.last_atom_and_free_list_table.putNoClobber(gpa, self.tbss_section_index.?, .{}); + } + } + if (self.symtab_section_index == null) { const min_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym); const each_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym); @@ -1295,6 +1335,12 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node self.phdrs.items[bss_phndx].p_offset = self.phdrs.items[data_phndx].p_offset; } + // Same treatment for .tbss section. + if (self.tdata_section_index) |tdata_shndx| blk: { + const tbss_shndx = self.tbss_section_index orelse break :blk; + self.shdrs.items[tbss_shndx].sh_offset = self.shdrs.items[tdata_shndx].sh_offset; + } + // Dump the state for easy debugging. // State can be dumped via `--debug-log link_state`. if (build_options.enable_logging) {