| ... | ... | @@ -247,7 +247,8 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf { |
| 247 | 247 | else |
| 248 | 248 | elf.VER_NDX_LOCAL; |
| 249 | 249 | |
| 250 | | var dwarf: ?Dwarf = if (!options.strip and options.module != null) |
| 250 | const use_llvm = options.use_llvm; |
| 251 | var dwarf: ?Dwarf = if (!options.strip and options.module != null and !use_llvm) |
| 251 | 252 | Dwarf.init(gpa, &self.base, options.target) |
| 252 | 253 | else |
| 253 | 254 | null; |
| ... | ... | @@ -264,7 +265,6 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf { |
| 264 | 265 | .page_size = page_size, |
| 265 | 266 | .default_sym_version = default_sym_version, |
| 266 | 267 | }; |
| 267 | | const use_llvm = options.use_llvm; |
| 268 | 268 | if (use_llvm and options.module != null) { |
| 269 | 269 | self.llvm_object = try LlvmObject.create(gpa, options); |
| 270 | 270 | } |
| ... | ... | @@ -643,6 +643,13 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 643 | 643 | } |
| 644 | 644 | |
| 645 | 645 | if (self.phdr_load_tls_zerofill_index == null) { |
| 646 | // TODO .tbss doesn't need any physical or memory representation (aka a loadable segment) |
| 647 | // since the loader only cares about the PT_TLS to work out TLS size. However, when |
| 648 | // relocating we need to have .tdata and .tbss contiguously laid out so that we can |
| 649 | // work out correct offsets to the start/end of the TLS segment. I am thinking that |
| 650 | // perhaps it's possible to completely spoof it by having an abstracted mechanism |
| 651 | // for this that wouldn't require us to explicitly track .tbss. Anyhow, for now, |
| 652 | // we go the savage route of treating .tbss like .bss. |
| 646 | 653 | const alignment = if (is_linux) self.page_size else @as(u16, ptr_size); |
| 647 | 654 | self.phdr_load_tls_zerofill_index = try self.allocateSegment(.{ |
| 648 | 655 | .size = 0, |
| ... | ... | @@ -655,6 +662,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 655 | 662 | } |
| 656 | 663 | |
| 657 | 664 | if (self.phdr_tls_index == null) { |
| 665 | self.phdr_tls_index = @intCast(self.phdrs.items.len); |
| 658 | 666 | const phdr_tdata = &self.phdrs.items[self.phdr_load_tls_data_index.?]; |
| 659 | 667 | const phdr_tbss = &self.phdrs.items[self.phdr_load_tls_zerofill_index.?]; |
| 660 | 668 | try self.phdrs.append(gpa, .{ |
| ... | ... | @@ -1280,6 +1288,36 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1280 | 1288 | try self.allocateObjects(); |
| 1281 | 1289 | self.allocateLinkerDefinedSymbols(); |
| 1282 | 1290 | |
| 1291 | // .bss always overlaps .data in file offset, but is zero-sized in file so it doesn't |
| 1292 | // get mapped by the loader |
| 1293 | if (self.data_section_index) |data_shndx| blk: { |
| 1294 | const bss_shndx = self.bss_section_index orelse break :blk; |
| 1295 | const data_phndx = self.phdr_to_shdr_table.get(data_shndx).?; |
| 1296 | const bss_phndx = self.phdr_to_shdr_table.get(bss_shndx).?; |
| 1297 | self.shdrs.items[bss_shndx].sh_offset = self.shdrs.items[data_shndx].sh_offset; |
| 1298 | self.phdrs.items[bss_phndx].p_offset = self.phdrs.items[data_phndx].p_offset; |
| 1299 | } |
| 1300 | |
| 1301 | // Same treatment for .tbss section. |
| 1302 | if (self.tdata_section_index) |tdata_shndx| blk: { |
| 1303 | const tbss_shndx = self.tbss_section_index orelse break :blk; |
| 1304 | const tdata_phndx = self.phdr_to_shdr_table.get(tdata_shndx).?; |
| 1305 | const tbss_phndx = self.phdr_to_shdr_table.get(tbss_shndx).?; |
| 1306 | self.shdrs.items[tbss_shndx].sh_offset = self.shdrs.items[tdata_shndx].sh_offset; |
| 1307 | self.phdrs.items[tbss_phndx].p_offset = self.phdrs.items[tdata_phndx].p_offset; |
| 1308 | } |
| 1309 | |
| 1310 | if (self.phdr_tls_index) |tls_index| { |
| 1311 | const tdata_phdr = &self.phdrs.items[self.phdr_load_tls_data_index.?]; |
| 1312 | const tbss_phdr = &self.phdrs.items[self.phdr_load_tls_zerofill_index.?]; |
| 1313 | const phdr = &self.phdrs.items[tls_index]; |
| 1314 | phdr.p_offset = tdata_phdr.p_offset; |
| 1315 | phdr.p_filesz = tdata_phdr.p_filesz; |
| 1316 | phdr.p_vaddr = tdata_phdr.p_vaddr; |
| 1317 | phdr.p_paddr = tdata_phdr.p_vaddr; |
| 1318 | phdr.p_memsz = tbss_phdr.p_vaddr + tbss_phdr.p_memsz - tdata_phdr.p_vaddr; |
| 1319 | } |
| 1320 | |
| 1283 | 1321 | // Beyond this point, everything has been allocated a virtual address and we can resolve |
| 1284 | 1322 | // the relocations, and commit objects to file. |
| 1285 | 1323 | if (self.zig_module_index) |index| { |
| ... | ... | @@ -1325,22 +1363,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1325 | 1363 | try self.updateSymtabSize(); |
| 1326 | 1364 | try self.writeSymtab(); |
| 1327 | 1365 | |
| 1328 | | // .bss always overlaps .data in file offset, but is zero-sized in file so it doesn't |
| 1329 | | // get mapped by the loader |
| 1330 | | if (self.data_section_index) |data_shndx| blk: { |
| 1331 | | const bss_shndx = self.bss_section_index orelse break :blk; |
| 1332 | | const data_phndx = self.phdr_to_shdr_table.get(data_shndx).?; |
| 1333 | | const bss_phndx = self.phdr_to_shdr_table.get(bss_shndx).?; |
| 1334 | | self.shdrs.items[bss_shndx].sh_offset = self.shdrs.items[data_shndx].sh_offset; |
| 1335 | | self.phdrs.items[bss_phndx].p_offset = self.phdrs.items[data_phndx].p_offset; |
| 1336 | | } |
| 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 | | |
| 1344 | 1366 | // Dump the state for easy debugging. |
| 1345 | 1367 | // State can be dumped via `--debug-log link_state`. |
| 1346 | 1368 | if (build_options.enable_logging) { |
| ... | ... | @@ -4066,6 +4088,22 @@ pub fn comdatGroupOwner(self: *Elf, index: ComdatGroupOwner.Index) *ComdatGroupO |
| 4066 | 4088 | return &self.comdat_groups_owners.items[index]; |
| 4067 | 4089 | } |
| 4068 | 4090 | |
| 4091 | pub fn tpAddress(self: *Elf) u64 { |
| 4092 | const index = self.phdr_tls_index orelse return 0; |
| 4093 | const phdr = self.phdrs.items[index]; |
| 4094 | return mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align); |
| 4095 | } |
| 4096 | |
| 4097 | pub fn dtpAddress(self: *Elf) u64 { |
| 4098 | return self.tlsAddress(); |
| 4099 | } |
| 4100 | |
| 4101 | pub fn tlsAddress(self: *Elf) u64 { |
| 4102 | const index = self.phdr_tls_index orelse return 0; |
| 4103 | const phdr = self.phdrs.items[index]; |
| 4104 | return phdr.p_vaddr; |
| 4105 | } |
| 4106 | |
| 4069 | 4107 | const ErrorWithNotes = struct { |
| 4070 | 4108 | /// Allocated index in misc_errors array. |
| 4071 | 4109 | index: usize, |