| ... | @@ -46,7 +46,9 @@ phdr_load_zerofill_index: ?u16 = null, | ... | @@ -46,7 +46,9 @@ phdr_load_zerofill_index: ?u16 = null, |
| 46 | /// The index into the program headers of the PT_TLS program header. | 46 | /// The index into the program headers of the PT_TLS program header. |
| 47 | phdr_tls_index: ?u16 = null, | 47 | phdr_tls_index: ?u16 = null, |
| 48 | /// The index into the program headers of a PT_LOAD program header with TLS data. | 48 | /// The index into the program headers of a PT_LOAD program header with TLS data. |
| 49 | phdr_load_tls_index: ?u16 = null, | 49 | phdr_load_tls_data_index: ?u16 = null, |
| | 50 | /// The index into the program headers of a PT_LOAD program header with TLS zerofill data. |
| | 51 | phdr_load_tls_zerofill_index: ?u16 = null, |
| 50 | | 52 | |
| 51 | entry_addr: ?u64 = null, | 53 | entry_addr: ?u64 = null, |
| 52 | page_size: u32, | 54 | page_size: u32, |
| ... | @@ -499,7 +501,7 @@ pub fn allocateAllocSection(self: *Elf, opts: AllocateAllocSectionOpts) error{Ou | ... | @@ -499,7 +501,7 @@ pub fn allocateAllocSection(self: *Elf, opts: AllocateAllocSectionOpts) error{Ou |
| 499 | .sh_flags = opts.flags, | 501 | .sh_flags = opts.flags, |
| 500 | .sh_addr = phdr.p_vaddr, | 502 | .sh_addr = phdr.p_vaddr, |
| 501 | .sh_offset = phdr.p_offset, | 503 | .sh_offset = phdr.p_offset, |
| 502 | .sh_size = phdr.p_filesz, | 504 | .sh_size = phdr.p_memsz, |
| 503 | .sh_link = 0, | 505 | .sh_link = 0, |
| 504 | .sh_info = 0, | 506 | .sh_info = 0, |
| 505 | .sh_addralign = opts.alignment, | 507 | .sh_addralign = opts.alignment, |
| ... | @@ -631,24 +633,37 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -631,24 +633,37 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 631 | } | 633 | } |
| 632 | | 634 | |
| 633 | if (!self.base.options.single_threaded) { | 635 | if (!self.base.options.single_threaded) { |
| 634 | if (self.phdr_load_tls_index == null) { | 636 | if (self.phdr_load_tls_data_index == null) { |
| 635 | const alignment = if (is_linux) self.page_size else @as(u16, ptr_size); | 637 | const alignment = if (is_linux) self.page_size else @as(u16, ptr_size); |
| 636 | self.phdr_load_tls_index = try self.allocateSegment(.{ | 638 | self.phdr_load_tls_data_index = try self.allocateSegment(.{ |
| 637 | .size = 1024, | 639 | .size = 1024, |
| 638 | .alignment = alignment, | 640 | .alignment = alignment, |
| 639 | .flags = elf.PF_R | elf.PF_W, | 641 | .flags = elf.PF_R | elf.PF_W, |
| 640 | }); | 642 | }); |
| 641 | } | 643 | } |
| 642 | | 644 | |
| | 645 | if (self.phdr_load_tls_zerofill_index == null) { |
| | 646 | const alignment = if (is_linux) self.page_size else @as(u16, ptr_size); |
| | 647 | self.phdr_load_tls_zerofill_index = try self.allocateSegment(.{ |
| | 648 | .size = 0, |
| | 649 | .alignment = alignment, |
| | 650 | .flags = elf.PF_R | elf.PF_W, |
| | 651 | }); |
| | 652 | const phdr = &self.phdrs.items[self.phdr_load_tls_zerofill_index.?]; |
| | 653 | phdr.p_offset = self.phdrs.items[self.phdr_load_tls_data_index.?].p_offset; // .tbss overlaps .tdata |
| | 654 | phdr.p_memsz = 1024; |
| | 655 | } |
| | 656 | |
| 643 | if (self.phdr_tls_index == null) { | 657 | if (self.phdr_tls_index == null) { |
| 644 | const phdr = &self.phdrs.items[self.phdr_load_tls_index.?]; | 658 | const phdr_tdata = &self.phdrs.items[self.phdr_load_tls_data_index.?]; |
| | 659 | const phdr_tbss = &self.phdrs.items[self.phdr_load_tls_zerofill_index.?]; |
| 645 | try self.phdrs.append(gpa, .{ | 660 | try self.phdrs.append(gpa, .{ |
| 646 | .p_type = elf.PT_TLS, | 661 | .p_type = elf.PT_TLS, |
| 647 | .p_offset = phdr.p_offset, | 662 | .p_offset = phdr_tdata.p_offset, |
| 648 | .p_vaddr = phdr.p_vaddr, | 663 | .p_vaddr = phdr_tdata.p_vaddr, |
| 649 | .p_paddr = phdr.p_paddr, | 664 | .p_paddr = phdr_tdata.p_paddr, |
| 650 | .p_filesz = phdr.p_filesz, | 665 | .p_filesz = phdr_tdata.p_filesz, |
| 651 | .p_memsz = phdr.p_memsz, | 666 | .p_memsz = phdr_tbss.p_vaddr + phdr_tbss.p_memsz - phdr_tdata.p_vaddr, |
| 652 | .p_align = ptr_size, | 667 | .p_align = ptr_size, |
| 653 | .p_flags = elf.PF_R, | 668 | .p_flags = elf.PF_R, |
| 654 | }); | 669 | }); |
| ... | @@ -724,6 +739,31 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -724,6 +739,31 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 724 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.bss_section_index.?, .{}); | 739 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.bss_section_index.?, .{}); |
| 725 | } | 740 | } |
| 726 | | 741 | |
| | 742 | if (self.phdr_load_tls_data_index) |phdr_index| { |
| | 743 | if (self.tdata_section_index == null) { |
| | 744 | self.tdata_section_index = try self.allocateAllocSection(.{ |
| | 745 | .name = ".tdata", |
| | 746 | .phdr_index = phdr_index, |
| | 747 | .alignment = ptr_size, |
| | 748 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS, |
| | 749 | }); |
| | 750 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.tdata_section_index.?, .{}); |
| | 751 | } |
| | 752 | } |
| | 753 | |
| | 754 | if (self.phdr_load_tls_zerofill_index) |phdr_index| { |
| | 755 | if (self.tbss_section_index == null) { |
| | 756 | self.tbss_section_index = try self.allocateAllocSection(.{ |
| | 757 | .name = ".tbss", |
| | 758 | .phdr_index = phdr_index, |
| | 759 | .alignment = ptr_size, |
| | 760 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS, |
| | 761 | .type = elf.SHT_NOBITS, |
| | 762 | }); |
| | 763 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.tbss_section_index.?, .{}); |
| | 764 | } |
| | 765 | } |
| | 766 | |
| 727 | if (self.symtab_section_index == null) { | 767 | if (self.symtab_section_index == null) { |
| 728 | const min_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym); | 768 | const min_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym); |
| 729 | const each_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym); | 769 | 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 | ... | @@ -1295,6 +1335,12 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1295 | self.phdrs.items[bss_phndx].p_offset = self.phdrs.items[data_phndx].p_offset; | 1335 | self.phdrs.items[bss_phndx].p_offset = self.phdrs.items[data_phndx].p_offset; |
| 1296 | } | 1336 | } |
| 1297 | | 1337 | |
| | 1338 | // Same treatment for .tbss section. |
| | 1339 | if (self.tdata_section_index) |tdata_shndx| blk: { |
| | 1340 | const tbss_shndx = self.tbss_section_index orelse break :blk; |
| | 1341 | self.shdrs.items[tbss_shndx].sh_offset = self.shdrs.items[tdata_shndx].sh_offset; |
| | 1342 | } |
| | 1343 | |
| 1298 | // Dump the state for easy debugging. | 1344 | // Dump the state for easy debugging. |
| 1299 | // State can be dumped via `--debug-log link_state`. | 1345 | // State can be dumped via `--debug-log link_state`. |
| 1300 | if (build_options.enable_logging) { | 1346 | if (build_options.enable_logging) { |