| ... | ... | @@ -46,7 +46,9 @@ phdr_load_zerofill_index: ?u16 = null, |
| 46 | 46 | /// The index into the program headers of the PT_TLS program header. |
| 47 | 47 | phdr_tls_index: ?u16 = null, |
| 48 | 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 | 53 | entry_addr: ?u64 = null, |
| 52 | 54 | page_size: u32, |
| ... | ... | @@ -499,7 +501,7 @@ pub fn allocateAllocSection(self: *Elf, opts: AllocateAllocSectionOpts) error{Ou |
| 499 | 501 | .sh_flags = opts.flags, |
| 500 | 502 | .sh_addr = phdr.p_vaddr, |
| 501 | 503 | .sh_offset = phdr.p_offset, |
| 502 | | .sh_size = phdr.p_filesz, |
| 504 | .sh_size = phdr.p_memsz, |
| 503 | 505 | .sh_link = 0, |
| 504 | 506 | .sh_info = 0, |
| 505 | 507 | .sh_addralign = opts.alignment, |
| ... | ... | @@ -631,24 +633,37 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 631 | 633 | } |
| 632 | 634 | |
| 633 | 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 | 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 | 639 | .size = 1024, |
| 638 | 640 | .alignment = alignment, |
| 639 | 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 | 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 | 660 | try self.phdrs.append(gpa, .{ |
| 646 | 661 | .p_type = elf.PT_TLS, |
| 647 | | .p_offset = phdr.p_offset, |
| 648 | | .p_vaddr = phdr.p_vaddr, |
| 649 | | .p_paddr = phdr.p_paddr, |
| 650 | | .p_filesz = phdr.p_filesz, |
| 651 | | .p_memsz = phdr.p_memsz, |
| 662 | .p_offset = phdr_tdata.p_offset, |
| 663 | .p_vaddr = phdr_tdata.p_vaddr, |
| 664 | .p_paddr = phdr_tdata.p_paddr, |
| 665 | .p_filesz = phdr_tdata.p_filesz, |
| 666 | .p_memsz = phdr_tbss.p_vaddr + phdr_tbss.p_memsz - phdr_tdata.p_vaddr, |
| 652 | 667 | .p_align = ptr_size, |
| 653 | 668 | .p_flags = elf.PF_R, |
| 654 | 669 | }); |
| ... | ... | @@ -724,6 +739,31 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 724 | 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 | 767 | if (self.symtab_section_index == null) { |
| 728 | 768 | const min_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym); |
| 729 | 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 | 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 | 1344 | // Dump the state for easy debugging. |
| 1299 | 1345 | // State can be dumped via `--debug-log link_state`. |
| 1300 | 1346 | if (build_options.enable_logging) { |