| author | |
| committer | |
| log | 30b4a87db711c368853b3eff8e214ab681810ef9 |
| tree | 7a2f72eeebba5f8fd6a457edee99ab6c720d4f5b |
| parent | f219286573a7a1edafe3e1b5bc1e521a379ee2e2 |
| parent | 3f10217a47ff259ca3671dd8bb89a04417bccdc2 |
| signature |
elf: clean up resource ownership in the linker17 files changed, 1203 insertions(+), 1006 deletions(-)
src/link/Elf.zig+166-532| ... | ... | @@ -54,7 +54,7 @@ phdr_to_shdr_table: std.AutoHashMapUnmanaged(u32, u32) = .{}, |
| 54 | 54 | shdr_table_offset: ?u64 = null, |
| 55 | 55 | /// Table of lists of atoms per output section. |
| 56 | 56 | /// This table is not used to track incrementally generated atoms. |
| 57 | output_sections: std.AutoArrayHashMapUnmanaged(u32, std.ArrayListUnmanaged(Atom.Index)) = .{}, | |
| 57 | output_sections: std.AutoArrayHashMapUnmanaged(u32, std.ArrayListUnmanaged(Ref)) = .{}, | |
| 58 | 58 | output_rela_sections: std.AutoArrayHashMapUnmanaged(u32, RelaSection) = .{}, |
| 59 | 59 | |
| 60 | 60 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. |
| ... | ... | @@ -93,7 +93,6 @@ phdr_gnu_stack_index: ?u16 = null, |
| 93 | 93 | /// TODO I think ELF permits multiple TLS segments but for now, assume one per file. |
| 94 | 94 | phdr_tls_index: ?u16 = null, |
| 95 | 95 | |
| 96 | entry_index: ?Symbol.Index = null, | |
| 97 | 96 | page_size: u32, |
| 98 | 97 | default_sym_version: elf.Elf64_Versym, |
| 99 | 98 | |
| ... | ... | @@ -174,25 +173,6 @@ shstrtab_section_index: ?u32 = null, |
| 174 | 173 | strtab_section_index: ?u32 = null, |
| 175 | 174 | symtab_section_index: ?u32 = null, |
| 176 | 175 | |
| 177 | // Linker-defined symbols | |
| 178 | dynamic_index: ?Symbol.Index = null, | |
| 179 | ehdr_start_index: ?Symbol.Index = null, | |
| 180 | init_array_start_index: ?Symbol.Index = null, | |
| 181 | init_array_end_index: ?Symbol.Index = null, | |
| 182 | fini_array_start_index: ?Symbol.Index = null, | |
| 183 | fini_array_end_index: ?Symbol.Index = null, | |
| 184 | preinit_array_start_index: ?Symbol.Index = null, | |
| 185 | preinit_array_end_index: ?Symbol.Index = null, | |
| 186 | got_index: ?Symbol.Index = null, | |
| 187 | plt_index: ?Symbol.Index = null, | |
| 188 | end_index: ?Symbol.Index = null, | |
| 189 | gnu_eh_frame_hdr_index: ?Symbol.Index = null, | |
| 190 | dso_handle_index: ?Symbol.Index = null, | |
| 191 | rela_iplt_start_index: ?Symbol.Index = null, | |
| 192 | rela_iplt_end_index: ?Symbol.Index = null, | |
| 193 | global_pointer_index: ?Symbol.Index = null, | |
| 194 | start_stop_indexes: std.ArrayListUnmanaged(u32) = .{}, | |
| 195 | ||
| 196 | 176 | /// An array of symbols parsed across all input files. |
| 197 | 177 | symbols: std.ArrayListUnmanaged(Symbol) = .{}, |
| 198 | 178 | symbols_extra: std.ArrayListUnmanaged(u32) = .{}, |
| ... | ... | @@ -203,30 +183,17 @@ resolver: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index) = .{}, |
| 203 | 183 | has_text_reloc: bool = false, |
| 204 | 184 | num_ifunc_dynrelocs: usize = 0, |
| 205 | 185 | |
| 206 | /// List of atoms that are owned directly by the linker. | |
| 207 | atoms: std.ArrayListUnmanaged(Atom) = .{}, | |
| 208 | atoms_extra: std.ArrayListUnmanaged(u32) = .{}, | |
| 209 | ||
| 210 | 186 | /// List of range extension thunks. |
| 211 | 187 | thunks: std.ArrayListUnmanaged(Thunk) = .{}, |
| 212 | 188 | |
| 213 | 189 | /// List of output merge sections with deduped contents. |
| 214 | 190 | merge_sections: std.ArrayListUnmanaged(MergeSection) = .{}, |
| 215 | /// List of output merge subsections. | |
| 216 | /// Each subsection is akin to Atom but belongs to a MergeSection. | |
| 217 | merge_subsections: std.ArrayListUnmanaged(MergeSubsection) = .{}, | |
| 218 | /// List of input merge sections as parsed from input relocatables. | |
| 219 | merge_input_sections: std.ArrayListUnmanaged(InputMergeSection) = .{}, | |
| 220 | 191 | |
| 221 | 192 | /// Table of last atom index in a section and matching atom free list if any. |
| 222 | 193 | last_atom_and_free_list_table: LastAtomAndFreeListTable = .{}, |
| 223 | 194 | |
| 224 | comdat_groups: std.ArrayListUnmanaged(ComdatGroup) = .{}, | |
| 225 | comdat_groups_owners: std.ArrayListUnmanaged(ComdatGroupOwner) = .{}, | |
| 226 | comdat_groups_table: std.AutoHashMapUnmanaged(u32, ComdatGroupOwner.Index) = .{}, | |
| 227 | ||
| 228 | 195 | /// Global string table used to provide quick access to global symbol resolvers |
| 229 | /// such as `resolver` and `comdat_groups_table`. | |
| 196 | /// such as `resolver`. | |
| 230 | 197 | strings: StringTable = .{}, |
| 231 | 198 | |
| 232 | 199 | first_eflags: ?elf.Elf64_Word = null, |
| ... | ... | @@ -378,20 +345,15 @@ pub fn createEmpty( |
| 378 | 345 | try self.symbols.append(gpa, .{}); |
| 379 | 346 | // Index 0 is always a null symbol. |
| 380 | 347 | try self.symbols_extra.append(gpa, 0); |
| 381 | // Allocate atom index 0 to null atom | |
| 382 | try self.atoms.append(gpa, .{}); | |
| 383 | try self.atoms_extra.append(gpa, 0); | |
| 384 | 348 | // Append null file at index 0 |
| 385 | 349 | try self.files.append(gpa, .null); |
| 386 | 350 | // Append null byte to string tables |
| 387 | 351 | try self.shstrtab.append(gpa, 0); |
| 388 | 352 | try self.strtab.append(gpa, 0); |
| 389 | 353 | // There must always be a null shdr in index 0 |
| 390 | _ = try self.addSection(.{ .name = "" }); | |
| 354 | _ = try self.addSection(.{}); | |
| 391 | 355 | // Append null symbol in output symtab |
| 392 | 356 | try self.symtab.append(gpa, null_sym); |
| 393 | // Append null input merge section. | |
| 394 | try self.merge_input_sections.append(gpa, .{}); | |
| 395 | 357 | |
| 396 | 358 | if (!is_obj_or_ar) { |
| 397 | 359 | try self.dynstrtab.append(gpa, 0); |
| ... | ... | @@ -502,10 +464,7 @@ pub fn deinit(self: *Elf) void { |
| 502 | 464 | self.symbols_extra.deinit(gpa); |
| 503 | 465 | self.symbols_free_list.deinit(gpa); |
| 504 | 466 | self.resolver.deinit(gpa); |
| 505 | self.start_stop_indexes.deinit(gpa); | |
| 506 | 467 | |
| 507 | self.atoms.deinit(gpa); | |
| 508 | self.atoms_extra.deinit(gpa); | |
| 509 | 468 | for (self.thunks.items) |*th| { |
| 510 | 469 | th.deinit(gpa); |
| 511 | 470 | } |
| ... | ... | @@ -514,19 +473,11 @@ pub fn deinit(self: *Elf) void { |
| 514 | 473 | sect.deinit(gpa); |
| 515 | 474 | } |
| 516 | 475 | self.merge_sections.deinit(gpa); |
| 517 | self.merge_subsections.deinit(gpa); | |
| 518 | for (self.merge_input_sections.items) |*sect| { | |
| 519 | sect.deinit(gpa); | |
| 520 | } | |
| 521 | self.merge_input_sections.deinit(gpa); | |
| 522 | 476 | for (self.last_atom_and_free_list_table.values()) |*value| { |
| 523 | 477 | value.free_list.deinit(gpa); |
| 524 | 478 | } |
| 525 | 479 | self.last_atom_and_free_list_table.deinit(gpa); |
| 526 | 480 | |
| 527 | self.comdat_groups.deinit(gpa); | |
| 528 | self.comdat_groups_owners.deinit(gpa); | |
| 529 | self.comdat_groups_table.deinit(gpa); | |
| 530 | 481 | self.strings.deinit(gpa); |
| 531 | 482 | |
| 532 | 483 | self.got.deinit(gpa); |
| ... | ... | @@ -744,7 +695,7 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void { |
| 744 | 695 | |
| 745 | 696 | if (self.zig_text_section_index == null) { |
| 746 | 697 | self.zig_text_section_index = try self.addSection(.{ |
| 747 | .name = ".text.zig", | |
| 698 | .name = try self.insertShString(".text.zig"), | |
| 748 | 699 | .type = elf.SHT_PROGBITS, |
| 749 | 700 | .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, |
| 750 | 701 | .addralign = 1, |
| ... | ... | @@ -753,7 +704,7 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void { |
| 753 | 704 | const shdr = &self.shdrs.items[self.zig_text_section_index.?]; |
| 754 | 705 | fillSection(self, shdr, options.program_code_size_hint, self.phdr_zig_load_re_index); |
| 755 | 706 | if (self.base.isRelocatable()) { |
| 756 | const rela_shndx = try self.addRelaShdr(".rela.text.zig", self.zig_text_section_index.?); | |
| 707 | const rela_shndx = try self.addRelaShdr(try self.insertShString(".rela.text.zig"), self.zig_text_section_index.?); | |
| 757 | 708 | try self.output_rela_sections.putNoClobber(gpa, self.zig_text_section_index.?, .{ |
| 758 | 709 | .shndx = rela_shndx, |
| 759 | 710 | }); |
| ... | ... | @@ -770,7 +721,7 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void { |
| 770 | 721 | |
| 771 | 722 | if (self.zig_got_section_index == null and !self.base.isRelocatable()) { |
| 772 | 723 | self.zig_got_section_index = try self.addSection(.{ |
| 773 | .name = ".got.zig", | |
| 724 | .name = try self.insertShString(".got.zig"), | |
| 774 | 725 | .type = elf.SHT_PROGBITS, |
| 775 | 726 | .addralign = ptr_size, |
| 776 | 727 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| ... | ... | @@ -791,7 +742,7 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void { |
| 791 | 742 | |
| 792 | 743 | if (self.zig_data_rel_ro_section_index == null) { |
| 793 | 744 | self.zig_data_rel_ro_section_index = try self.addSection(.{ |
| 794 | .name = ".data.rel.ro.zig", | |
| 745 | .name = try self.insertShString(".data.rel.ro.zig"), | |
| 795 | 746 | .type = elf.SHT_PROGBITS, |
| 796 | 747 | .addralign = 1, |
| 797 | 748 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| ... | ... | @@ -801,7 +752,7 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void { |
| 801 | 752 | fillSection(self, shdr, 1024, self.phdr_zig_load_ro_index); |
| 802 | 753 | if (self.base.isRelocatable()) { |
| 803 | 754 | const rela_shndx = try self.addRelaShdr( |
| 804 | ".rela.data.rel.ro.zig", | |
| 755 | try self.insertShString(".rela.data.rel.ro.zig"), | |
| 805 | 756 | self.zig_data_rel_ro_section_index.?, |
| 806 | 757 | ); |
| 807 | 758 | try self.output_rela_sections.putNoClobber(gpa, self.zig_data_rel_ro_section_index.?, .{ |
| ... | ... | @@ -820,7 +771,7 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void { |
| 820 | 771 | |
| 821 | 772 | if (self.zig_data_section_index == null) { |
| 822 | 773 | self.zig_data_section_index = try self.addSection(.{ |
| 823 | .name = ".data.zig", | |
| 774 | .name = try self.insertShString(".data.zig"), | |
| 824 | 775 | .type = elf.SHT_PROGBITS, |
| 825 | 776 | .addralign = ptr_size, |
| 826 | 777 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| ... | ... | @@ -830,7 +781,7 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void { |
| 830 | 781 | fillSection(self, shdr, 1024, self.phdr_zig_load_rw_index); |
| 831 | 782 | if (self.base.isRelocatable()) { |
| 832 | 783 | const rela_shndx = try self.addRelaShdr( |
| 833 | ".rela.data.zig", | |
| 784 | try self.insertShString(".rela.data.zig"), | |
| 834 | 785 | self.zig_data_section_index.?, |
| 835 | 786 | ); |
| 836 | 787 | try self.output_rela_sections.putNoClobber(gpa, self.zig_data_section_index.?, .{ |
| ... | ... | @@ -849,7 +800,7 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void { |
| 849 | 800 | |
| 850 | 801 | if (self.zig_bss_section_index == null) { |
| 851 | 802 | self.zig_bss_section_index = try self.addSection(.{ |
| 852 | .name = ".bss.zig", | |
| 803 | .name = try self.insertShString(".bss.zig"), | |
| 853 | 804 | .type = elf.SHT_NOBITS, |
| 854 | 805 | .addralign = ptr_size, |
| 855 | 806 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| ... | ... | @@ -873,7 +824,7 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void { |
| 873 | 824 | assert(dw.strtab.buffer.items.len == 0); |
| 874 | 825 | try dw.strtab.buffer.append(gpa, 0); |
| 875 | 826 | self.debug_str_section_index = try self.addSection(.{ |
| 876 | .name = ".debug_str", | |
| 827 | .name = try self.insertShString(".debug_str"), | |
| 877 | 828 | .flags = elf.SHF_MERGE | elf.SHF_STRINGS, |
| 878 | 829 | .entsize = 1, |
| 879 | 830 | .type = elf.SHT_PROGBITS, |
| ... | ... | @@ -891,7 +842,7 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void { |
| 891 | 842 | |
| 892 | 843 | if (self.debug_info_section_index == null) { |
| 893 | 844 | self.debug_info_section_index = try self.addSection(.{ |
| 894 | .name = ".debug_info", | |
| 845 | .name = try self.insertShString(".debug_info"), | |
| 895 | 846 | .type = elf.SHT_PROGBITS, |
| 896 | 847 | .addralign = 1, |
| 897 | 848 | .offset = std.math.maxInt(u64), |
| ... | ... | @@ -907,7 +858,7 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void { |
| 907 | 858 | |
| 908 | 859 | if (self.debug_abbrev_section_index == null) { |
| 909 | 860 | self.debug_abbrev_section_index = try self.addSection(.{ |
| 910 | .name = ".debug_abbrev", | |
| 861 | .name = try self.insertShString(".debug_abbrev"), | |
| 911 | 862 | .type = elf.SHT_PROGBITS, |
| 912 | 863 | .addralign = 1, |
| 913 | 864 | .offset = std.math.maxInt(u64), |
| ... | ... | @@ -923,7 +874,7 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void { |
| 923 | 874 | |
| 924 | 875 | if (self.debug_aranges_section_index == null) { |
| 925 | 876 | self.debug_aranges_section_index = try self.addSection(.{ |
| 926 | .name = ".debug_aranges", | |
| 877 | .name = try self.insertShString(".debug_aranges"), | |
| 927 | 878 | .type = elf.SHT_PROGBITS, |
| 928 | 879 | .addralign = 16, |
| 929 | 880 | .offset = std.math.maxInt(u64), |
| ... | ... | @@ -939,7 +890,7 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void { |
| 939 | 890 | |
| 940 | 891 | if (self.debug_line_section_index == null) { |
| 941 | 892 | self.debug_line_section_index = try self.addSection(.{ |
| 942 | .name = ".debug_line", | |
| 893 | .name = try self.insertShString(".debug_line"), | |
| 943 | 894 | .type = elf.SHT_PROGBITS, |
| 944 | 895 | .addralign = 1, |
| 945 | 896 | .offset = std.math.maxInt(u64), |
| ... | ... | @@ -1315,6 +1266,9 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 1315 | 1266 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); |
| 1316 | 1267 | self.files.set(index, .{ .linker_defined = .{ .index = index } }); |
| 1317 | 1268 | self.linker_defined_index = index; |
| 1269 | const object = self.linkerDefinedPtr().?; | |
| 1270 | try object.init(gpa); | |
| 1271 | try object.initSymbols(self); | |
| 1318 | 1272 | } |
| 1319 | 1273 | |
| 1320 | 1274 | // Now, we are ready to resolve the symbols across all input files. |
| ... | ... | @@ -1322,20 +1276,13 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 1322 | 1276 | // input Object files. |
| 1323 | 1277 | // Any qualifing unresolved symbol will be upgraded to an absolute, weak |
| 1324 | 1278 | // symbol for potential resolution at load-time. |
| 1325 | self.resolveSymbols(); | |
| 1279 | try self.resolveSymbols(); | |
| 1326 | 1280 | self.markEhFrameAtomsDead(); |
| 1327 | 1281 | try self.resolveMergeSections(); |
| 1328 | 1282 | |
| 1329 | 1283 | try self.convertCommonSymbols(); |
| 1330 | 1284 | self.markImportsExports(); |
| 1331 | 1285 | |
| 1332 | // Look for entry address in objects if not set by the incremental compiler. | |
| 1333 | if (self.entry_index == null) { | |
| 1334 | if (self.entry_name) |name| { | |
| 1335 | self.entry_index = self.globalByName(name); | |
| 1336 | } | |
| 1337 | } | |
| 1338 | ||
| 1339 | 1286 | if (self.base.gc_sections) { |
| 1340 | 1287 | try gc.gcAtoms(self); |
| 1341 | 1288 | |
| ... | ... | @@ -1353,7 +1300,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 1353 | 1300 | try self.finalizeMergeSections(); |
| 1354 | 1301 | try self.initOutputSections(); |
| 1355 | 1302 | try self.initMergeSections(); |
| 1356 | try self.addLinkerDefinedSymbols(); | |
| 1357 | 1303 | self.claimUnresolved(); |
| 1358 | 1304 | |
| 1359 | 1305 | // Scan and create missing synthetic entries such as GOT indirection. |
| ... | ... | @@ -1379,7 +1325,9 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 1379 | 1325 | try self.sortPhdrs(); |
| 1380 | 1326 | try self.allocateNonAllocSections(); |
| 1381 | 1327 | self.allocateSpecialPhdrs(); |
| 1382 | self.allocateLinkerDefinedSymbols(); | |
| 1328 | if (self.linkerDefinedPtr()) |obj| { | |
| 1329 | obj.allocateSymbols(self); | |
| 1330 | } | |
| 1383 | 1331 | |
| 1384 | 1332 | // Dump the state for easy debugging. |
| 1385 | 1333 | // State can be dumped via `--debug-log link_state`. |
| ... | ... | @@ -1389,15 +1337,15 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 1389 | 1337 | |
| 1390 | 1338 | // Beyond this point, everything has been allocated a virtual address and we can resolve |
| 1391 | 1339 | // the relocations, and commit objects to file. |
| 1392 | if (self.zigObjectPtr()) |zig_object| { | |
| 1340 | if (self.zigObjectPtr()) |zo| { | |
| 1393 | 1341 | var has_reloc_errors = false; |
| 1394 | for (zig_object.atoms.items) |atom_index| { | |
| 1395 | const atom_ptr = self.atom(atom_index) orelse continue; | |
| 1396 | if (!atom_ptr.flags.alive) continue; | |
| 1397 | const out_shndx = atom_ptr.outputShndx() orelse continue; | |
| 1342 | for (zo.atoms_indexes.items) |atom_index| { | |
| 1343 | const atom_ptr = zo.atom(atom_index) orelse continue; | |
| 1344 | if (!atom_ptr.alive) continue; | |
| 1345 | const out_shndx = atom_ptr.output_section_index; | |
| 1398 | 1346 | const shdr = &self.shdrs.items[out_shndx]; |
| 1399 | 1347 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| 1400 | const code = try zig_object.codeAlloc(self, atom_index); | |
| 1348 | const code = try zo.codeAlloc(self, atom_index); | |
| 1401 | 1349 | defer gpa.free(code); |
| 1402 | 1350 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); |
| 1403 | 1351 | atom_ptr.resolveRelocsAlloc(self, code) catch |err| switch (err) { |
| ... | ... | @@ -1427,7 +1375,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 1427 | 1375 | else => |e| return e, |
| 1428 | 1376 | }; |
| 1429 | 1377 | |
| 1430 | if (self.entry_index == null and self.base.isExe()) { | |
| 1378 | if (self.base.isExe() and self.linkerDefinedPtr().?.entry_index == null) { | |
| 1431 | 1379 | log.debug("flushing. no_entry_point_found = true", .{}); |
| 1432 | 1380 | comp.link_error_flags.no_entry_point_found = true; |
| 1433 | 1381 | } else { |
| ... | ... | @@ -1972,12 +1920,13 @@ fn accessLibPath( |
| 1972 | 1920 | /// 4. Reset state of all resolved globals since we will redo this bit on the pruned set. |
| 1973 | 1921 | /// 5. Remove references to dead objects/shared objects |
| 1974 | 1922 | /// 6. Re-run symbol resolution on pruned objects and shared objects sets. |
| 1975 | pub fn resolveSymbols(self: *Elf) void { | |
| 1923 | pub fn resolveSymbols(self: *Elf) !void { | |
| 1976 | 1924 | // Resolve symbols in the ZigObject. For now, we assume that it's always live. |
| 1977 | 1925 | if (self.zigObjectPtr()) |zig_object| zig_object.asFile().resolveSymbols(self); |
| 1978 | 1926 | // Resolve symbols on the set of all objects and shared objects (even if some are unneeded). |
| 1979 | 1927 | for (self.objects.items) |index| self.file(index).?.resolveSymbols(self); |
| 1980 | 1928 | for (self.shared_objects.items) |index| self.file(index).?.resolveSymbols(self); |
| 1929 | if (self.linkerDefinedPtr()) |obj| obj.asFile().resolveSymbols(self); | |
| 1981 | 1930 | |
| 1982 | 1931 | // Mark live objects. |
| 1983 | 1932 | self.markLive(); |
| ... | ... | @@ -1986,6 +1935,7 @@ pub fn resolveSymbols(self: *Elf) void { |
| 1986 | 1935 | if (self.zigObjectPtr()) |zig_object| zig_object.asFile().resetGlobals(self); |
| 1987 | 1936 | for (self.objects.items) |index| self.file(index).?.resetGlobals(self); |
| 1988 | 1937 | for (self.shared_objects.items) |index| self.file(index).?.resetGlobals(self); |
| 1938 | if (self.linkerDefinedPtr()) |obj| obj.asFile().resetGlobals(self); | |
| 1989 | 1939 | |
| 1990 | 1940 | // Prune dead objects and shared objects. |
| 1991 | 1941 | var i: usize = 0; |
| ... | ... | @@ -2003,41 +1953,25 @@ pub fn resolveSymbols(self: *Elf) void { |
| 2003 | 1953 | } else i += 1; |
| 2004 | 1954 | } |
| 2005 | 1955 | |
| 2006 | // Dedup comdat groups. | |
| 2007 | for (self.objects.items) |index| { | |
| 2008 | const object = self.file(index).?.object; | |
| 2009 | for (object.comdat_groups.items) |cg_index| { | |
| 2010 | const cg = self.comdatGroup(cg_index); | |
| 2011 | const cg_owner = self.comdatGroupOwner(cg.owner); | |
| 2012 | const owner_file_index = if (self.file(cg_owner.file)) |file_ptr| | |
| 2013 | file_ptr.object.index | |
| 2014 | else | |
| 2015 | std.math.maxInt(File.Index); | |
| 2016 | cg_owner.file = @min(owner_file_index, index); | |
| 1956 | { | |
| 1957 | // Dedup comdat groups. | |
| 1958 | var table = std.StringHashMap(Ref).init(self.base.comp.gpa); | |
| 1959 | defer table.deinit(); | |
| 1960 | ||
| 1961 | for (self.objects.items) |index| { | |
| 1962 | try self.file(index).?.object.resolveComdatGroups(self, &table); | |
| 2017 | 1963 | } |
| 2018 | } | |
| 2019 | 1964 | |
| 2020 | for (self.objects.items) |index| { | |
| 2021 | const object = self.file(index).?.object; | |
| 2022 | for (object.comdat_groups.items) |cg_index| { | |
| 2023 | const cg = self.comdatGroup(cg_index); | |
| 2024 | const cg_owner = self.comdatGroupOwner(cg.owner); | |
| 2025 | if (cg_owner.file != index) { | |
| 2026 | for (cg.comdatGroupMembers(self)) |shndx| { | |
| 2027 | const atom_index = object.atoms.items[shndx]; | |
| 2028 | if (self.atom(atom_index)) |atom_ptr| { | |
| 2029 | atom_ptr.flags.alive = false; | |
| 2030 | atom_ptr.markFdesDead(self); | |
| 2031 | } | |
| 2032 | } | |
| 2033 | } | |
| 1965 | for (self.objects.items) |index| { | |
| 1966 | self.file(index).?.object.markComdatGroupsDead(self); | |
| 2034 | 1967 | } |
| 2035 | 1968 | } |
| 2036 | 1969 | |
| 2037 | 1970 | // Re-resolve the symbols. |
| 2038 | if (self.zigObjectPtr()) |zig_object| zig_object.resolveSymbols(self); | |
| 1971 | if (self.zigObjectPtr()) |zig_object| zig_object.asFile().resolveSymbols(self); | |
| 2039 | 1972 | for (self.objects.items) |index| self.file(index).?.resolveSymbols(self); |
| 2040 | 1973 | for (self.shared_objects.items) |index| self.file(index).?.resolveSymbols(self); |
| 1974 | if (self.linkerDefinedPtr()) |obj| obj.asFile().resolveSymbols(self); | |
| 2041 | 1975 | } |
| 2042 | 1976 | |
| 2043 | 1977 | /// Traverses all objects and shared objects marking any object referenced by |
| ... | ... | @@ -2129,7 +2063,7 @@ fn claimUnresolved(self: *Elf) void { |
| 2129 | 2063 | fn scanRelocs(self: *Elf) !void { |
| 2130 | 2064 | const gpa = self.base.comp.gpa; |
| 2131 | 2065 | |
| 2132 | var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Atom.Index)).init(gpa); | |
| 2066 | var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Ref)).init(gpa); | |
| 2133 | 2067 | defer { |
| 2134 | 2068 | var it = undefs.iterator(); |
| 2135 | 2069 | while (it.next()) |entry| { |
| ... | ... | @@ -2976,10 +2910,10 @@ pub fn writeElfHeader(self: *Elf) !void { |
| 2976 | 2910 | mem.writeInt(u32, hdr_buf[index..][0..4], 1, endian); |
| 2977 | 2911 | index += 4; |
| 2978 | 2912 | |
| 2979 | const e_entry = if (self.entry_index) |entry_index| | |
| 2980 | @as(u64, @intCast(self.symbol(entry_index).address(.{}, self))) | |
| 2981 | else | |
| 2982 | 0; | |
| 2913 | const e_entry: u64 = if (self.linkerDefinedPtr()) |obj| blk: { | |
| 2914 | const entry_index = obj.entry_index orelse break :blk 0; | |
| 2915 | break :blk @intCast(self.symbol(entry_index).address(.{}, self)); | |
| 2916 | } else 0; | |
| 2983 | 2917 | const phdr_table_offset = if (self.phdr_table_index) |phndx| self.phdrs.items[phndx].p_offset else 0; |
| 2984 | 2918 | switch (self.ptr_width) { |
| 2985 | 2919 | .p32 => { |
| ... | ... | @@ -3106,205 +3040,6 @@ pub fn deleteExport( |
| 3106 | 3040 | return self.zigObjectPtr().?.deleteExport(self, exported, name); |
| 3107 | 3041 | } |
| 3108 | 3042 | |
| 3109 | fn addLinkerDefinedSymbols(self: *Elf) !void { | |
| 3110 | const comp = self.base.comp; | |
| 3111 | const gpa = comp.gpa; | |
| 3112 | ||
| 3113 | const linker_defined_index = self.linker_defined_index orelse return; | |
| 3114 | const linker_defined = self.file(linker_defined_index).?.linker_defined; | |
| 3115 | self.dynamic_index = try linker_defined.addGlobal("_DYNAMIC", self); | |
| 3116 | self.ehdr_start_index = try linker_defined.addGlobal("__ehdr_start", self); | |
| 3117 | self.init_array_start_index = try linker_defined.addGlobal("__init_array_start", self); | |
| 3118 | self.init_array_end_index = try linker_defined.addGlobal("__init_array_end", self); | |
| 3119 | self.fini_array_start_index = try linker_defined.addGlobal("__fini_array_start", self); | |
| 3120 | self.fini_array_end_index = try linker_defined.addGlobal("__fini_array_end", self); | |
| 3121 | self.preinit_array_start_index = try linker_defined.addGlobal("__preinit_array_start", self); | |
| 3122 | self.preinit_array_end_index = try linker_defined.addGlobal("__preinit_array_end", self); | |
| 3123 | self.got_index = try linker_defined.addGlobal("_GLOBAL_OFFSET_TABLE_", self); | |
| 3124 | self.plt_index = try linker_defined.addGlobal("_PROCEDURE_LINKAGE_TABLE_", self); | |
| 3125 | self.end_index = try linker_defined.addGlobal("_end", self); | |
| 3126 | ||
| 3127 | if (comp.link_eh_frame_hdr) { | |
| 3128 | self.gnu_eh_frame_hdr_index = try linker_defined.addGlobal("__GNU_EH_FRAME_HDR", self); | |
| 3129 | } | |
| 3130 | ||
| 3131 | if (self.globalByName("__dso_handle")) |index| { | |
| 3132 | if (self.symbol(index).file(self) == null) | |
| 3133 | self.dso_handle_index = try linker_defined.addGlobal("__dso_handle", self); | |
| 3134 | } | |
| 3135 | ||
| 3136 | self.rela_iplt_start_index = try linker_defined.addGlobal("__rela_iplt_start", self); | |
| 3137 | self.rela_iplt_end_index = try linker_defined.addGlobal("__rela_iplt_end", self); | |
| 3138 | ||
| 3139 | for (self.shdrs.items) |shdr| { | |
| 3140 | if (self.getStartStopBasename(shdr)) |name| { | |
| 3141 | try self.start_stop_indexes.ensureUnusedCapacity(gpa, 2); | |
| 3142 | ||
| 3143 | const start = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name}); | |
| 3144 | defer gpa.free(start); | |
| 3145 | const stop = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name}); | |
| 3146 | defer gpa.free(stop); | |
| 3147 | ||
| 3148 | self.start_stop_indexes.appendAssumeCapacity(try linker_defined.addGlobal(start, self)); | |
| 3149 | self.start_stop_indexes.appendAssumeCapacity(try linker_defined.addGlobal(stop, self)); | |
| 3150 | } | |
| 3151 | } | |
| 3152 | ||
| 3153 | if (self.getTarget().cpu.arch.isRISCV() and self.isEffectivelyDynLib()) { | |
| 3154 | self.global_pointer_index = try linker_defined.addGlobal("__global_pointer$", self); | |
| 3155 | } | |
| 3156 | ||
| 3157 | linker_defined.resolveSymbols(self); | |
| 3158 | } | |
| 3159 | ||
| 3160 | fn allocateLinkerDefinedSymbols(self: *Elf) void { | |
| 3161 | const comp = self.base.comp; | |
| 3162 | const link_mode = comp.config.link_mode; | |
| 3163 | ||
| 3164 | // _DYNAMIC | |
| 3165 | if (self.dynamic_section_index) |shndx| { | |
| 3166 | const shdr = &self.shdrs.items[shndx]; | |
| 3167 | const symbol_ptr = self.symbol(self.dynamic_index.?); | |
| 3168 | symbol_ptr.value = @intCast(shdr.sh_addr); | |
| 3169 | symbol_ptr.output_section_index = shndx; | |
| 3170 | } | |
| 3171 | ||
| 3172 | // __ehdr_start | |
| 3173 | { | |
| 3174 | const symbol_ptr = self.symbol(self.ehdr_start_index.?); | |
| 3175 | symbol_ptr.value = @intCast(self.image_base); | |
| 3176 | symbol_ptr.output_section_index = 1; | |
| 3177 | } | |
| 3178 | ||
| 3179 | // __init_array_start, __init_array_end | |
| 3180 | if (self.sectionByName(".init_array")) |shndx| { | |
| 3181 | const start_sym = self.symbol(self.init_array_start_index.?); | |
| 3182 | const end_sym = self.symbol(self.init_array_end_index.?); | |
| 3183 | const shdr = &self.shdrs.items[shndx]; | |
| 3184 | start_sym.output_section_index = shndx; | |
| 3185 | start_sym.value = @intCast(shdr.sh_addr); | |
| 3186 | end_sym.output_section_index = shndx; | |
| 3187 | end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size); | |
| 3188 | } | |
| 3189 | ||
| 3190 | // __fini_array_start, __fini_array_end | |
| 3191 | if (self.sectionByName(".fini_array")) |shndx| { | |
| 3192 | const start_sym = self.symbol(self.fini_array_start_index.?); | |
| 3193 | const end_sym = self.symbol(self.fini_array_end_index.?); | |
| 3194 | const shdr = &self.shdrs.items[shndx]; | |
| 3195 | start_sym.output_section_index = shndx; | |
| 3196 | start_sym.value = @intCast(shdr.sh_addr); | |
| 3197 | end_sym.output_section_index = shndx; | |
| 3198 | end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size); | |
| 3199 | } | |
| 3200 | ||
| 3201 | // __preinit_array_start, __preinit_array_end | |
| 3202 | if (self.sectionByName(".preinit_array")) |shndx| { | |
| 3203 | const start_sym = self.symbol(self.preinit_array_start_index.?); | |
| 3204 | const end_sym = self.symbol(self.preinit_array_end_index.?); | |
| 3205 | const shdr = &self.shdrs.items[shndx]; | |
| 3206 | start_sym.output_section_index = shndx; | |
| 3207 | start_sym.value = @intCast(shdr.sh_addr); | |
| 3208 | end_sym.output_section_index = shndx; | |
| 3209 | end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size); | |
| 3210 | } | |
| 3211 | ||
| 3212 | // _GLOBAL_OFFSET_TABLE_ | |
| 3213 | if (self.getTarget().cpu.arch == .x86_64) { | |
| 3214 | if (self.got_plt_section_index) |shndx| { | |
| 3215 | const shdr = self.shdrs.items[shndx]; | |
| 3216 | const sym = self.symbol(self.got_index.?); | |
| 3217 | sym.value = @intCast(shdr.sh_addr); | |
| 3218 | sym.output_section_index = shndx; | |
| 3219 | } | |
| 3220 | } else { | |
| 3221 | if (self.got_section_index) |shndx| { | |
| 3222 | const shdr = self.shdrs.items[shndx]; | |
| 3223 | const sym = self.symbol(self.got_index.?); | |
| 3224 | sym.value = @intCast(shdr.sh_addr); | |
| 3225 | sym.output_section_index = shndx; | |
| 3226 | } | |
| 3227 | } | |
| 3228 | ||
| 3229 | // _PROCEDURE_LINKAGE_TABLE_ | |
| 3230 | if (self.plt_section_index) |shndx| { | |
| 3231 | const shdr = &self.shdrs.items[shndx]; | |
| 3232 | const symbol_ptr = self.symbol(self.plt_index.?); | |
| 3233 | symbol_ptr.value = @intCast(shdr.sh_addr); | |
| 3234 | symbol_ptr.output_section_index = shndx; | |
| 3235 | } | |
| 3236 | ||
| 3237 | // __dso_handle | |
| 3238 | if (self.dso_handle_index) |index| { | |
| 3239 | const shdr = &self.shdrs.items[1]; | |
| 3240 | const symbol_ptr = self.symbol(index); | |
| 3241 | symbol_ptr.value = @intCast(shdr.sh_addr); | |
| 3242 | symbol_ptr.output_section_index = 0; | |
| 3243 | } | |
| 3244 | ||
| 3245 | // __GNU_EH_FRAME_HDR | |
| 3246 | if (self.eh_frame_hdr_section_index) |shndx| { | |
| 3247 | const shdr = &self.shdrs.items[shndx]; | |
| 3248 | const symbol_ptr = self.symbol(self.gnu_eh_frame_hdr_index.?); | |
| 3249 | symbol_ptr.value = @intCast(shdr.sh_addr); | |
| 3250 | symbol_ptr.output_section_index = shndx; | |
| 3251 | } | |
| 3252 | ||
| 3253 | // __rela_iplt_start, __rela_iplt_end | |
| 3254 | if (self.rela_dyn_section_index) |shndx| blk: { | |
| 3255 | if (link_mode != .static or comp.config.pie) break :blk; | |
| 3256 | const shdr = &self.shdrs.items[shndx]; | |
| 3257 | const end_addr = shdr.sh_addr + shdr.sh_size; | |
| 3258 | const start_addr = end_addr - self.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela); | |
| 3259 | const start_sym = self.symbol(self.rela_iplt_start_index.?); | |
| 3260 | const end_sym = self.symbol(self.rela_iplt_end_index.?); | |
| 3261 | start_sym.value = @intCast(start_addr); | |
| 3262 | start_sym.output_section_index = shndx; | |
| 3263 | end_sym.value = @intCast(end_addr); | |
| 3264 | end_sym.output_section_index = shndx; | |
| 3265 | } | |
| 3266 | ||
| 3267 | // _end | |
| 3268 | { | |
| 3269 | const end_symbol = self.symbol(self.end_index.?); | |
| 3270 | for (self.shdrs.items, 0..) |shdr, shndx| { | |
| 3271 | if (shdr.sh_flags & elf.SHF_ALLOC != 0) { | |
| 3272 | end_symbol.value = @intCast(shdr.sh_addr + shdr.sh_size); | |
| 3273 | end_symbol.output_section_index = @intCast(shndx); | |
| 3274 | } | |
| 3275 | } | |
| 3276 | } | |
| 3277 | ||
| 3278 | // __start_*, __stop_* | |
| 3279 | { | |
| 3280 | var index: usize = 0; | |
| 3281 | while (index < self.start_stop_indexes.items.len) : (index += 2) { | |
| 3282 | const start = self.symbol(self.start_stop_indexes.items[index]); | |
| 3283 | const name = start.name(self); | |
| 3284 | const stop = self.symbol(self.start_stop_indexes.items[index + 1]); | |
| 3285 | const shndx = self.sectionByName(name["__start_".len..]).?; | |
| 3286 | const shdr = &self.shdrs.items[shndx]; | |
| 3287 | start.value = @intCast(shdr.sh_addr); | |
| 3288 | start.output_section_index = shndx; | |
| 3289 | stop.value = @intCast(shdr.sh_addr + shdr.sh_size); | |
| 3290 | stop.output_section_index = shndx; | |
| 3291 | } | |
| 3292 | } | |
| 3293 | ||
| 3294 | // __global_pointer$ | |
| 3295 | if (self.global_pointer_index) |index| { | |
| 3296 | const sym = self.symbol(index); | |
| 3297 | if (self.sectionByName(".sdata")) |shndx| { | |
| 3298 | const shdr = self.shdrs.items[shndx]; | |
| 3299 | sym.value = @intCast(shdr.sh_addr + 0x800); | |
| 3300 | sym.output_section_index = shndx; | |
| 3301 | } else { | |
| 3302 | sym.value = 0; | |
| 3303 | sym.output_section_index = 0; | |
| 3304 | } | |
| 3305 | } | |
| 3306 | } | |
| 3307 | ||
| 3308 | 3043 | fn checkDuplicates(self: *Elf) !void { |
| 3309 | 3044 | const gpa = self.base.comp.gpa; |
| 3310 | 3045 | |
| ... | ... | @@ -3327,12 +3062,13 @@ fn checkDuplicates(self: *Elf) !void { |
| 3327 | 3062 | } |
| 3328 | 3063 | |
| 3329 | 3064 | pub fn addCommentString(self: *Elf) !void { |
| 3065 | const gpa = self.base.comp.gpa; | |
| 3330 | 3066 | const msec_index = try self.getOrCreateMergeSection(".comment", elf.SHF_MERGE | elf.SHF_STRINGS, elf.SHT_PROGBITS); |
| 3331 | 3067 | const msec = self.mergeSection(msec_index); |
| 3332 | const res = try msec.insertZ(self.base.comp.gpa, "zig " ++ builtin.zig_version_string); | |
| 3068 | const res = try msec.insertZ(gpa, "zig " ++ builtin.zig_version_string); | |
| 3333 | 3069 | if (res.found_existing) return; |
| 3334 | const msub_index = try self.addMergeSubsection(); | |
| 3335 | const msub = self.mergeSubsection(msub_index); | |
| 3070 | const msub_index = try msec.addMergeSubsection(gpa); | |
| 3071 | const msub = msec.mergeSubsection(msub_index); | |
| 3336 | 3072 | msub.merge_section_index = msec_index; |
| 3337 | 3073 | msub.string_index = res.key.pos; |
| 3338 | 3074 | msub.alignment = .@"1"; |
| ... | ... | @@ -3350,7 +3086,7 @@ pub fn resolveMergeSections(self: *Elf) !void { |
| 3350 | 3086 | for (self.objects.items) |index| { |
| 3351 | 3087 | const file_ptr = self.file(index).?; |
| 3352 | 3088 | if (!file_ptr.isAlive()) continue; |
| 3353 | file_ptr.object.initMergeSections(self) catch |err| switch (err) { | |
| 3089 | file_ptr.object.initInputMergeSections(self) catch |err| switch (err) { | |
| 3354 | 3090 | error.MalformedObject => has_errors = true, |
| 3355 | 3091 | else => |e| return e, |
| 3356 | 3092 | }; |
| ... | ... | @@ -3358,6 +3094,12 @@ pub fn resolveMergeSections(self: *Elf) !void { |
| 3358 | 3094 | |
| 3359 | 3095 | if (has_errors) return error.FlushFailure; |
| 3360 | 3096 | |
| 3097 | for (self.objects.items) |index| { | |
| 3098 | const file_ptr = self.file(index).?; | |
| 3099 | if (!file_ptr.isAlive()) continue; | |
| 3100 | try file_ptr.object.initOutputMergeSections(self); | |
| 3101 | } | |
| 3102 | ||
| 3361 | 3103 | for (self.objects.items) |index| { |
| 3362 | 3104 | const file_ptr = self.file(index).?; |
| 3363 | 3105 | if (!file_ptr.isAlive()) continue; |
| ... | ... | @@ -3372,15 +3114,15 @@ pub fn resolveMergeSections(self: *Elf) !void { |
| 3372 | 3114 | |
| 3373 | 3115 | pub fn finalizeMergeSections(self: *Elf) !void { |
| 3374 | 3116 | for (self.merge_sections.items) |*msec| { |
| 3375 | try msec.finalize(self); | |
| 3117 | try msec.finalize(self.base.comp.gpa); | |
| 3376 | 3118 | } |
| 3377 | 3119 | } |
| 3378 | 3120 | |
| 3379 | 3121 | pub fn updateMergeSectionSizes(self: *Elf) !void { |
| 3380 | 3122 | for (self.merge_sections.items) |*msec| { |
| 3381 | 3123 | const shdr = &self.shdrs.items[msec.output_section_index]; |
| 3382 | for (msec.subsections.items) |msub_index| { | |
| 3383 | const msub = self.mergeSubsection(msub_index); | |
| 3124 | for (msec.finalized_subsections.items) |msub_index| { | |
| 3125 | const msub = msec.mergeSubsection(msub_index); | |
| 3384 | 3126 | assert(msub.alive); |
| 3385 | 3127 | const offset = msub.alignment.forward(shdr.sh_size); |
| 3386 | 3128 | const padding = offset - shdr.sh_size; |
| ... | ... | @@ -3396,14 +3138,14 @@ pub fn writeMergeSections(self: *Elf) !void { |
| 3396 | 3138 | var buffer = std.ArrayList(u8).init(gpa); |
| 3397 | 3139 | defer buffer.deinit(); |
| 3398 | 3140 | |
| 3399 | for (self.merge_sections.items) |msec| { | |
| 3141 | for (self.merge_sections.items) |*msec| { | |
| 3400 | 3142 | const shdr = self.shdrs.items[msec.output_section_index]; |
| 3401 | 3143 | const size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; |
| 3402 | 3144 | try buffer.ensureTotalCapacity(size); |
| 3403 | 3145 | buffer.appendNTimesAssumeCapacity(0, size); |
| 3404 | 3146 | |
| 3405 | for (msec.subsections.items) |msub_index| { | |
| 3406 | const msub = self.mergeSubsection(msub_index); | |
| 3147 | for (msec.finalized_subsections.items) |msub_index| { | |
| 3148 | const msub = msec.mergeSubsection(msub_index); | |
| 3407 | 3149 | assert(msub.alive); |
| 3408 | 3150 | const string = msub.getString(self); |
| 3409 | 3151 | const off = math.cast(usize, msub.value) orelse return error.Overflow; |
| ... | ... | @@ -3423,18 +3165,18 @@ fn initOutputSections(self: *Elf) !void { |
| 3423 | 3165 | |
| 3424 | 3166 | pub fn initMergeSections(self: *Elf) !void { |
| 3425 | 3167 | for (self.merge_sections.items) |*msec| { |
| 3426 | if (msec.subsections.items.len == 0) continue; | |
| 3168 | if (msec.finalized_subsections.items.len == 0) continue; | |
| 3427 | 3169 | const name = msec.name(self); |
| 3428 | 3170 | const shndx = self.sectionByName(name) orelse try self.addSection(.{ |
| 3429 | .name = name, | |
| 3171 | .name = msec.name_offset, | |
| 3430 | 3172 | .type = msec.type, |
| 3431 | 3173 | .flags = msec.flags, |
| 3432 | 3174 | }); |
| 3433 | 3175 | msec.output_section_index = shndx; |
| 3434 | 3176 | |
| 3435 | var entsize = self.mergeSubsection(msec.subsections.items[0]).entsize; | |
| 3436 | for (msec.subsections.items) |index| { | |
| 3437 | const msub = self.mergeSubsection(index); | |
| 3177 | var entsize = msec.mergeSubsection(msec.finalized_subsections.items[0]).entsize; | |
| 3178 | for (msec.finalized_subsections.items) |msub_index| { | |
| 3179 | const msub = msec.mergeSubsection(msub_index); | |
| 3438 | 3180 | entsize = @min(entsize, msub.entsize); |
| 3439 | 3181 | } |
| 3440 | 3182 | const shdr = &self.shdrs.items[shndx]; |
| ... | ... | @@ -3452,7 +3194,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3452 | 3194 | } else false; |
| 3453 | 3195 | if (needs_eh_frame) { |
| 3454 | 3196 | self.eh_frame_section_index = try self.addSection(.{ |
| 3455 | .name = ".eh_frame", | |
| 3197 | .name = try self.insertShString(".eh_frame"), | |
| 3456 | 3198 | .type = elf.SHT_PROGBITS, |
| 3457 | 3199 | .flags = elf.SHF_ALLOC, |
| 3458 | 3200 | .addralign = ptr_size, |
| ... | ... | @@ -3461,7 +3203,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3461 | 3203 | |
| 3462 | 3204 | if (comp.link_eh_frame_hdr) { |
| 3463 | 3205 | self.eh_frame_hdr_section_index = try self.addSection(.{ |
| 3464 | .name = ".eh_frame_hdr", | |
| 3206 | .name = try self.insertShString(".eh_frame_hdr"), | |
| 3465 | 3207 | .type = elf.SHT_PROGBITS, |
| 3466 | 3208 | .flags = elf.SHF_ALLOC, |
| 3467 | 3209 | .addralign = 4, |
| ... | ... | @@ -3472,7 +3214,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3472 | 3214 | |
| 3473 | 3215 | if (self.got.entries.items.len > 0) { |
| 3474 | 3216 | self.got_section_index = try self.addSection(.{ |
| 3475 | .name = ".got", | |
| 3217 | .name = try self.insertShString(".got"), | |
| 3476 | 3218 | .type = elf.SHT_PROGBITS, |
| 3477 | 3219 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| 3478 | 3220 | .addralign = ptr_size, |
| ... | ... | @@ -3481,7 +3223,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3481 | 3223 | } |
| 3482 | 3224 | |
| 3483 | 3225 | self.got_plt_section_index = try self.addSection(.{ |
| 3484 | .name = ".got.plt", | |
| 3226 | .name = try self.insertShString(".got.plt"), | |
| 3485 | 3227 | .type = elf.SHT_PROGBITS, |
| 3486 | 3228 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| 3487 | 3229 | .addralign = @alignOf(u64), |
| ... | ... | @@ -3501,7 +3243,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3501 | 3243 | }; |
| 3502 | 3244 | if (needs_rela_dyn) { |
| 3503 | 3245 | self.rela_dyn_section_index = try self.addSection(.{ |
| 3504 | .name = ".rela.dyn", | |
| 3246 | .name = try self.insertShString(".rela.dyn"), | |
| 3505 | 3247 | .type = elf.SHT_RELA, |
| 3506 | 3248 | .flags = elf.SHF_ALLOC, |
| 3507 | 3249 | .addralign = @alignOf(elf.Elf64_Rela), |
| ... | ... | @@ -3512,14 +3254,14 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3512 | 3254 | |
| 3513 | 3255 | if (self.plt.symbols.items.len > 0) { |
| 3514 | 3256 | self.plt_section_index = try self.addSection(.{ |
| 3515 | .name = ".plt", | |
| 3257 | .name = try self.insertShString(".plt"), | |
| 3516 | 3258 | .type = elf.SHT_PROGBITS, |
| 3517 | 3259 | .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, |
| 3518 | 3260 | .addralign = 16, |
| 3519 | 3261 | .offset = std.math.maxInt(u64), |
| 3520 | 3262 | }); |
| 3521 | 3263 | self.rela_plt_section_index = try self.addSection(.{ |
| 3522 | .name = ".rela.plt", | |
| 3264 | .name = try self.insertShString(".rela.plt"), | |
| 3523 | 3265 | .type = elf.SHT_RELA, |
| 3524 | 3266 | .flags = elf.SHF_ALLOC, |
| 3525 | 3267 | .addralign = @alignOf(elf.Elf64_Rela), |
| ... | ... | @@ -3530,7 +3272,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3530 | 3272 | |
| 3531 | 3273 | if (self.plt_got.symbols.items.len > 0) { |
| 3532 | 3274 | self.plt_got_section_index = try self.addSection(.{ |
| 3533 | .name = ".plt.got", | |
| 3275 | .name = try self.insertShString(".plt.got"), | |
| 3534 | 3276 | .type = elf.SHT_PROGBITS, |
| 3535 | 3277 | .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, |
| 3536 | 3278 | .addralign = 16, |
| ... | ... | @@ -3540,7 +3282,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3540 | 3282 | |
| 3541 | 3283 | if (self.copy_rel.symbols.items.len > 0) { |
| 3542 | 3284 | self.copy_rel_section_index = try self.addSection(.{ |
| 3543 | .name = ".copyrel", | |
| 3285 | .name = try self.insertShString(".copyrel"), | |
| 3544 | 3286 | .type = elf.SHT_NOBITS, |
| 3545 | 3287 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| 3546 | 3288 | .offset = std.math.maxInt(u64), |
| ... | ... | @@ -3558,7 +3300,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3558 | 3300 | }; |
| 3559 | 3301 | if (needs_interp) { |
| 3560 | 3302 | self.interp_section_index = try self.addSection(.{ |
| 3561 | .name = ".interp", | |
| 3303 | .name = try self.insertShString(".interp"), | |
| 3562 | 3304 | .type = elf.SHT_PROGBITS, |
| 3563 | 3305 | .flags = elf.SHF_ALLOC, |
| 3564 | 3306 | .addralign = 1, |
| ... | ... | @@ -3568,7 +3310,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3568 | 3310 | |
| 3569 | 3311 | if (self.isEffectivelyDynLib() or self.shared_objects.items.len > 0 or comp.config.pie) { |
| 3570 | 3312 | self.dynstrtab_section_index = try self.addSection(.{ |
| 3571 | .name = ".dynstr", | |
| 3313 | .name = try self.insertShString(".dynstr"), | |
| 3572 | 3314 | .flags = elf.SHF_ALLOC, |
| 3573 | 3315 | .type = elf.SHT_STRTAB, |
| 3574 | 3316 | .entsize = 1, |
| ... | ... | @@ -3576,7 +3318,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3576 | 3318 | .offset = std.math.maxInt(u64), |
| 3577 | 3319 | }); |
| 3578 | 3320 | self.dynamic_section_index = try self.addSection(.{ |
| 3579 | .name = ".dynamic", | |
| 3321 | .name = try self.insertShString(".dynamic"), | |
| 3580 | 3322 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| 3581 | 3323 | .type = elf.SHT_DYNAMIC, |
| 3582 | 3324 | .entsize = @sizeOf(elf.Elf64_Dyn), |
| ... | ... | @@ -3584,7 +3326,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3584 | 3326 | .offset = std.math.maxInt(u64), |
| 3585 | 3327 | }); |
| 3586 | 3328 | self.dynsymtab_section_index = try self.addSection(.{ |
| 3587 | .name = ".dynsym", | |
| 3329 | .name = try self.insertShString(".dynsym"), | |
| 3588 | 3330 | .flags = elf.SHF_ALLOC, |
| 3589 | 3331 | .type = elf.SHT_DYNSYM, |
| 3590 | 3332 | .addralign = @alignOf(elf.Elf64_Sym), |
| ... | ... | @@ -3593,7 +3335,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3593 | 3335 | .offset = std.math.maxInt(u64), |
| 3594 | 3336 | }); |
| 3595 | 3337 | self.hash_section_index = try self.addSection(.{ |
| 3596 | .name = ".hash", | |
| 3338 | .name = try self.insertShString(".hash"), | |
| 3597 | 3339 | .flags = elf.SHF_ALLOC, |
| 3598 | 3340 | .type = elf.SHT_HASH, |
| 3599 | 3341 | .addralign = 4, |
| ... | ... | @@ -3601,7 +3343,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3601 | 3343 | .offset = std.math.maxInt(u64), |
| 3602 | 3344 | }); |
| 3603 | 3345 | self.gnu_hash_section_index = try self.addSection(.{ |
| 3604 | .name = ".gnu.hash", | |
| 3346 | .name = try self.insertShString(".gnu.hash"), | |
| 3605 | 3347 | .flags = elf.SHF_ALLOC, |
| 3606 | 3348 | .type = elf.SHT_GNU_HASH, |
| 3607 | 3349 | .addralign = 8, |
| ... | ... | @@ -3614,7 +3356,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3614 | 3356 | } else false; |
| 3615 | 3357 | if (needs_versions) { |
| 3616 | 3358 | self.versym_section_index = try self.addSection(.{ |
| 3617 | .name = ".gnu.version", | |
| 3359 | .name = try self.insertShString(".gnu.version"), | |
| 3618 | 3360 | .flags = elf.SHF_ALLOC, |
| 3619 | 3361 | .type = elf.SHT_GNU_VERSYM, |
| 3620 | 3362 | .addralign = @alignOf(elf.Elf64_Versym), |
| ... | ... | @@ -3622,7 +3364,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3622 | 3364 | .offset = std.math.maxInt(u64), |
| 3623 | 3365 | }); |
| 3624 | 3366 | self.verneed_section_index = try self.addSection(.{ |
| 3625 | .name = ".gnu.version_r", | |
| 3367 | .name = try self.insertShString(".gnu.version_r"), | |
| 3626 | 3368 | .flags = elf.SHF_ALLOC, |
| 3627 | 3369 | .type = elf.SHT_GNU_VERNEED, |
| 3628 | 3370 | .addralign = @alignOf(elf.Elf64_Verneed), |
| ... | ... | @@ -3642,7 +3384,7 @@ pub fn initSymtab(self: *Elf) !void { |
| 3642 | 3384 | }; |
| 3643 | 3385 | if (self.symtab_section_index == null) { |
| 3644 | 3386 | self.symtab_section_index = try self.addSection(.{ |
| 3645 | .name = ".symtab", | |
| 3387 | .name = try self.insertShString(".symtab"), | |
| 3646 | 3388 | .type = elf.SHT_SYMTAB, |
| 3647 | 3389 | .addralign = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym), |
| 3648 | 3390 | .entsize = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym), |
| ... | ... | @@ -3651,7 +3393,7 @@ pub fn initSymtab(self: *Elf) !void { |
| 3651 | 3393 | } |
| 3652 | 3394 | if (self.strtab_section_index == null) { |
| 3653 | 3395 | self.strtab_section_index = try self.addSection(.{ |
| 3654 | .name = ".strtab", | |
| 3396 | .name = try self.insertShString(".strtab"), | |
| 3655 | 3397 | .type = elf.SHT_STRTAB, |
| 3656 | 3398 | .entsize = 1, |
| 3657 | 3399 | .addralign = 1, |
| ... | ... | @@ -3663,7 +3405,7 @@ pub fn initSymtab(self: *Elf) !void { |
| 3663 | 3405 | pub fn initShStrtab(self: *Elf) !void { |
| 3664 | 3406 | if (self.shstrtab_section_index == null) { |
| 3665 | 3407 | self.shstrtab_section_index = try self.addSection(.{ |
| 3666 | .name = ".shstrtab", | |
| 3408 | .name = try self.insertShString(".shstrtab"), | |
| 3667 | 3409 | .type = elf.SHT_STRTAB, |
| 3668 | 3410 | .entsize = 1, |
| 3669 | 3411 | .addralign = 1, |
| ... | ... | @@ -3733,11 +3475,11 @@ fn sortInitFini(self: *Elf) !void { |
| 3733 | 3475 | |
| 3734 | 3476 | const Entry = struct { |
| 3735 | 3477 | priority: i32, |
| 3736 | atom_index: Atom.Index, | |
| 3478 | atom_ref: Ref, | |
| 3737 | 3479 | |
| 3738 | 3480 | pub fn lessThan(ctx: *Elf, lhs: @This(), rhs: @This()) bool { |
| 3739 | 3481 | if (lhs.priority == rhs.priority) { |
| 3740 | return ctx.atom(lhs.atom_index).?.priority(ctx) < ctx.atom(rhs.atom_index).?.priority(ctx); | |
| 3482 | return ctx.atom(lhs.atom_ref).?.priority(ctx) < ctx.atom(rhs.atom_ref).?.priority(ctx); | |
| 3741 | 3483 | } |
| 3742 | 3484 | return lhs.priority < rhs.priority; |
| 3743 | 3485 | } |
| ... | ... | @@ -3768,8 +3510,8 @@ fn sortInitFini(self: *Elf) !void { |
| 3768 | 3510 | try entries.ensureTotalCapacityPrecise(atom_list.items.len); |
| 3769 | 3511 | defer entries.deinit(); |
| 3770 | 3512 | |
| 3771 | for (atom_list.items) |atom_index| { | |
| 3772 | const atom_ptr = self.atom(atom_index).?; | |
| 3513 | for (atom_list.items) |ref| { | |
| 3514 | const atom_ptr = self.atom(ref).?; | |
| 3773 | 3515 | const object = atom_ptr.file(self).?.object; |
| 3774 | 3516 | const priority = blk: { |
| 3775 | 3517 | if (is_ctor_dtor) { |
| ... | ... | @@ -3782,14 +3524,14 @@ fn sortInitFini(self: *Elf) !void { |
| 3782 | 3524 | const priority = std.fmt.parseUnsigned(u16, it.first(), 10) catch default; |
| 3783 | 3525 | break :blk priority; |
| 3784 | 3526 | }; |
| 3785 | entries.appendAssumeCapacity(.{ .priority = priority, .atom_index = atom_index }); | |
| 3527 | entries.appendAssumeCapacity(.{ .priority = priority, .atom_ref = ref }); | |
| 3786 | 3528 | } |
| 3787 | 3529 | |
| 3788 | 3530 | mem.sort(Entry, entries.items, self, Entry.lessThan); |
| 3789 | 3531 | |
| 3790 | 3532 | atom_list.clearRetainingCapacity(); |
| 3791 | 3533 | for (entries.items) |entry| { |
| 3792 | atom_list.appendAssumeCapacity(entry.atom_index); | |
| 3534 | atom_list.appendAssumeCapacity(entry.atom_ref); | |
| 3793 | 3535 | } |
| 3794 | 3536 | } |
| 3795 | 3537 | } |
| ... | ... | @@ -4155,26 +3897,11 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) !void { |
| 4155 | 3897 | } |
| 4156 | 3898 | } |
| 4157 | 3899 | |
| 4158 | if (self.zigObjectPtr()) |zig_object| { | |
| 4159 | for (zig_object.atoms.items) |atom_index| { | |
| 4160 | const atom_ptr = self.atom(atom_index) orelse continue; | |
| 3900 | if (self.zigObjectPtr()) |zo| { | |
| 3901 | for (zo.atoms_indexes.items) |atom_index| { | |
| 3902 | const atom_ptr = zo.atom(atom_index) orelse continue; | |
| 4161 | 3903 | atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index]; |
| 4162 | 3904 | } |
| 4163 | ||
| 4164 | for (zig_object.locals()) |local_index| { | |
| 4165 | const local = self.symbol(local_index); | |
| 4166 | local.output_section_index = backlinks[local.output_section_index]; | |
| 4167 | } | |
| 4168 | ||
| 4169 | for (zig_object.globals()) |global_index| { | |
| 4170 | const global = self.symbol(global_index); | |
| 4171 | const atom_ptr = global.atom(self) orelse continue; | |
| 4172 | if (!atom_ptr.flags.alive) continue; | |
| 4173 | // TODO claim unresolved for objects | |
| 4174 | if (global.file(self).?.index() != zig_object.index) continue; | |
| 4175 | const out_shndx = global.outputShndx() orelse continue; | |
| 4176 | global.output_section_index = backlinks[out_shndx]; | |
| 4177 | } | |
| 4178 | 3905 | } |
| 4179 | 3906 | |
| 4180 | 3907 | for (self.output_rela_sections.keys(), self.output_rela_sections.values()) |shndx, sec| { |
| ... | ... | @@ -4194,9 +3921,9 @@ fn updateSectionSizes(self: *Elf) !void { |
| 4194 | 3921 | const shdr = &self.shdrs.items[shndx]; |
| 4195 | 3922 | if (atom_list.items.len == 0) continue; |
| 4196 | 3923 | if (self.requiresThunks() and shdr.sh_flags & elf.SHF_EXECINSTR != 0) continue; |
| 4197 | for (atom_list.items) |atom_index| { | |
| 4198 | const atom_ptr = self.atom(atom_index) orelse continue; | |
| 4199 | if (!atom_ptr.flags.alive) continue; | |
| 3924 | for (atom_list.items) |ref| { | |
| 3925 | const atom_ptr = self.atom(ref) orelse continue; | |
| 3926 | if (!atom_ptr.alive) continue; | |
| 4200 | 3927 | const offset = atom_ptr.alignment.forward(shdr.sh_size); |
| 4201 | 3928 | const padding = offset - shdr.sh_size; |
| 4202 | 3929 | atom_ptr.value = @intCast(offset); |
| ... | ... | @@ -4630,7 +4357,7 @@ fn allocateSpecialPhdrs(self: *Elf) void { |
| 4630 | 4357 | fn writeAtoms(self: *Elf) !void { |
| 4631 | 4358 | const gpa = self.base.comp.gpa; |
| 4632 | 4359 | |
| 4633 | var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Atom.Index)).init(gpa); | |
| 4360 | var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Ref)).init(gpa); | |
| 4634 | 4361 | defer { |
| 4635 | 4362 | var it = undefs.iterator(); |
| 4636 | 4363 | while (it.next()) |entry| { |
| ... | ... | @@ -4678,21 +4405,21 @@ fn writeAtoms(self: *Elf) !void { |
| 4678 | 4405 | 0; |
| 4679 | 4406 | @memset(buffer, padding_byte); |
| 4680 | 4407 | |
| 4681 | for (atom_list.items) |atom_index| { | |
| 4682 | const atom_ptr = self.atom(atom_index).?; | |
| 4683 | assert(atom_ptr.flags.alive); | |
| 4408 | for (atom_list.items) |ref| { | |
| 4409 | const atom_ptr = self.atom(ref).?; | |
| 4410 | assert(atom_ptr.alive); | |
| 4684 | 4411 | |
| 4685 | 4412 | const offset = math.cast(usize, atom_ptr.value - @as(i64, @intCast(base_offset))) orelse |
| 4686 | 4413 | return error.Overflow; |
| 4687 | 4414 | const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow; |
| 4688 | 4415 | |
| 4689 | log.debug("writing atom({d}) at 0x{x}", .{ atom_index, sh_offset + offset }); | |
| 4416 | log.debug("writing atom({}) at 0x{x}", .{ ref, sh_offset + offset }); | |
| 4690 | 4417 | |
| 4691 | 4418 | // TODO decompress directly into provided buffer |
| 4692 | 4419 | const out_code = buffer[offset..][0..size]; |
| 4693 | 4420 | const in_code = switch (atom_ptr.file(self).?) { |
| 4694 | .object => |x| try x.codeDecompressAlloc(self, atom_index), | |
| 4695 | .zig_object => |x| try x.codeAlloc(self, atom_index), | |
| 4421 | .object => |x| try x.codeDecompressAlloc(self, ref.index), | |
| 4422 | .zig_object => |x| try x.codeAlloc(self, ref.index), | |
| 4696 | 4423 | else => unreachable, |
| 4697 | 4424 | }; |
| 4698 | 4425 | defer gpa.free(in_code); |
| ... | ... | @@ -5015,9 +4742,8 @@ pub fn writeSymtab(self: *Elf) !void { |
| 5015 | 4742 | file_ptr.writeSymtab(self); |
| 5016 | 4743 | } |
| 5017 | 4744 | |
| 5018 | if (self.linker_defined_index) |index| { | |
| 5019 | const file_ptr = self.file(index).?; | |
| 5020 | file_ptr.writeSymtab(self); | |
| 4745 | if (self.linkerDefinedPtr()) |obj| { | |
| 4746 | obj.asFile().writeSymtab(self); | |
| 5021 | 4747 | } |
| 5022 | 4748 | |
| 5023 | 4749 | if (self.zig_got_section_index) |_| { |
| ... | ... | @@ -5479,7 +5205,7 @@ fn addPhdr(self: *Elf, opts: struct { |
| 5479 | 5205 | return index; |
| 5480 | 5206 | } |
| 5481 | 5207 | |
| 5482 | pub fn addRelaShdr(self: *Elf, name: [:0]const u8, shndx: u32) !u32 { | |
| 5208 | pub fn addRelaShdr(self: *Elf, name: u32, shndx: u32) !u32 { | |
| 5483 | 5209 | const entsize: u64 = switch (self.ptr_width) { |
| 5484 | 5210 | .p32 => @sizeOf(elf.Elf32_Rela), |
| 5485 | 5211 | .p64 => @sizeOf(elf.Elf64_Rela), |
| ... | ... | @@ -5500,7 +5226,7 @@ pub fn addRelaShdr(self: *Elf, name: [:0]const u8, shndx: u32) !u32 { |
| 5500 | 5226 | } |
| 5501 | 5227 | |
| 5502 | 5228 | pub const AddSectionOpts = struct { |
| 5503 | name: [:0]const u8, | |
| 5229 | name: u32 = 0, | |
| 5504 | 5230 | type: u32 = elf.SHT_NULL, |
| 5505 | 5231 | flags: u64 = 0, |
| 5506 | 5232 | link: u32 = 0, |
| ... | ... | @@ -5515,7 +5241,7 @@ pub fn addSection(self: *Elf, opts: AddSectionOpts) !u32 { |
| 5515 | 5241 | const index = @as(u32, @intCast(self.shdrs.items.len)); |
| 5516 | 5242 | const shdr = try self.shdrs.addOne(gpa); |
| 5517 | 5243 | shdr.* = .{ |
| 5518 | .sh_name = try self.insertShString(opts.name), | |
| 5244 | .sh_name = opts.name, | |
| 5519 | 5245 | .sh_type = opts.type, |
| 5520 | 5246 | .sh_flags = opts.flags, |
| 5521 | 5247 | .sh_addr = 0, |
| ... | ... | @@ -5580,7 +5306,7 @@ fn sortRelaDyn(self: *Elf) void { |
| 5580 | 5306 | mem.sort(elf.Elf64_Rela, self.rela_dyn.items, self, Sort.lessThan); |
| 5581 | 5307 | } |
| 5582 | 5308 | |
| 5583 | fn calcNumIRelativeRelocs(self: *Elf) usize { | |
| 5309 | pub fn calcNumIRelativeRelocs(self: *Elf) usize { | |
| 5584 | 5310 | var count: usize = self.num_ifunc_dynrelocs; |
| 5585 | 5311 | |
| 5586 | 5312 | for (self.got.entries.items) |entry| { |
| ... | ... | @@ -5602,7 +5328,7 @@ pub fn isCIdentifier(name: []const u8) bool { |
| 5602 | 5328 | return true; |
| 5603 | 5329 | } |
| 5604 | 5330 | |
| 5605 | fn getStartStopBasename(self: *Elf, shdr: elf.Elf64_Shdr) ?[]const u8 { | |
| 5331 | pub fn getStartStopBasename(self: *Elf, shdr: elf.Elf64_Shdr) ?[]const u8 { | |
| 5606 | 5332 | const name = self.getShString(shdr.sh_name); |
| 5607 | 5333 | if (shdr.sh_flags & elf.SHF_ALLOC != 0 and name.len > 0) { |
| 5608 | 5334 | if (isCIdentifier(name)) return name; |
| ... | ... | @@ -5610,64 +5336,6 @@ fn getStartStopBasename(self: *Elf, shdr: elf.Elf64_Shdr) ?[]const u8 { |
| 5610 | 5336 | return null; |
| 5611 | 5337 | } |
| 5612 | 5338 | |
| 5613 | pub fn atom(self: *Elf, atom_index: Atom.Index) ?*Atom { | |
| 5614 | if (atom_index == 0) return null; | |
| 5615 | assert(atom_index < self.atoms.items.len); | |
| 5616 | return &self.atoms.items[atom_index]; | |
| 5617 | } | |
| 5618 | ||
| 5619 | pub fn addAtom(self: *Elf) !Atom.Index { | |
| 5620 | const gpa = self.base.comp.gpa; | |
| 5621 | const index = @as(Atom.Index, @intCast(self.atoms.items.len)); | |
| 5622 | const atom_ptr = try self.atoms.addOne(gpa); | |
| 5623 | atom_ptr.* = .{ .atom_index = index }; | |
| 5624 | return index; | |
| 5625 | } | |
| 5626 | ||
| 5627 | pub fn addAtomExtra(self: *Elf, extra: Atom.Extra) !u32 { | |
| 5628 | const fields = @typeInfo(Atom.Extra).Struct.fields; | |
| 5629 | try self.atoms_extra.ensureUnusedCapacity(self.base.comp.gpa, fields.len); | |
| 5630 | return self.addAtomExtraAssumeCapacity(extra); | |
| 5631 | } | |
| 5632 | ||
| 5633 | pub fn addAtomExtraAssumeCapacity(self: *Elf, extra: Atom.Extra) u32 { | |
| 5634 | const index = @as(u32, @intCast(self.atoms_extra.items.len)); | |
| 5635 | const fields = @typeInfo(Atom.Extra).Struct.fields; | |
| 5636 | inline for (fields) |field| { | |
| 5637 | self.atoms_extra.appendAssumeCapacity(switch (field.type) { | |
| 5638 | u32 => @field(extra, field.name), | |
| 5639 | else => @compileError("bad field type"), | |
| 5640 | }); | |
| 5641 | } | |
| 5642 | return index; | |
| 5643 | } | |
| 5644 | ||
| 5645 | pub fn atomExtra(self: *Elf, index: u32) ?Atom.Extra { | |
| 5646 | if (index == 0) return null; | |
| 5647 | const fields = @typeInfo(Atom.Extra).Struct.fields; | |
| 5648 | var i: usize = index; | |
| 5649 | var result: Atom.Extra = undefined; | |
| 5650 | inline for (fields) |field| { | |
| 5651 | @field(result, field.name) = switch (field.type) { | |
| 5652 | u32 => self.atoms_extra.items[i], | |
| 5653 | else => @compileError("bad field type"), | |
| 5654 | }; | |
| 5655 | i += 1; | |
| 5656 | } | |
| 5657 | return result; | |
| 5658 | } | |
| 5659 | ||
| 5660 | pub fn setAtomExtra(self: *Elf, index: u32, extra: Atom.Extra) void { | |
| 5661 | assert(index > 0); | |
| 5662 | const fields = @typeInfo(Atom.Extra).Struct.fields; | |
| 5663 | inline for (fields, 0..) |field, i| { | |
| 5664 | self.atoms_extra.items[index + i] = switch (field.type) { | |
| 5665 | u32 => @field(extra, field.name), | |
| 5666 | else => @compileError("bad field type"), | |
| 5667 | }; | |
| 5668 | } | |
| 5669 | } | |
| 5670 | ||
| 5671 | 5339 | pub fn addThunk(self: *Elf) !Thunk.Index { |
| 5672 | 5340 | const index = @as(Thunk.Index, @intCast(self.thunks.items.len)); |
| 5673 | 5341 | const th = try self.thunks.addOne(self.base.comp.gpa); |
| ... | ... | @@ -5704,6 +5372,15 @@ pub fn fileHandle(self: Elf, index: File.HandleIndex) File.Handle { |
| 5704 | 5372 | return self.file_handles.items[index]; |
| 5705 | 5373 | } |
| 5706 | 5374 | |
| 5375 | pub fn atom(self: *Elf, ref: Ref) ?*Atom { | |
| 5376 | const file_ptr = self.file(ref.file) orelse return null; | |
| 5377 | return file_ptr.atom(ref.index); | |
| 5378 | } | |
| 5379 | ||
| 5380 | pub fn comdatGroup(self: *Elf, ref: Ref) *ComdatGroup { | |
| 5381 | return self.file(ref.file).?.comdatGroup(ref.index); | |
| 5382 | } | |
| 5383 | ||
| 5707 | 5384 | /// Returns pointer-to-symbol described at sym_index. |
| 5708 | 5385 | pub fn symbol(self: *Elf, sym_index: Symbol.Index) *Symbol { |
| 5709 | 5386 | return &self.symbols.items[sym_index]; |
| ... | ... | @@ -5795,11 +5472,6 @@ pub fn getOrPutGlobal(self: *Elf, name: []const u8) !GetOrPutGlobalResult { |
| 5795 | 5472 | }; |
| 5796 | 5473 | } |
| 5797 | 5474 | |
| 5798 | pub fn globalByName(self: *Elf, name: []const u8) ?Symbol.Index { | |
| 5799 | const name_off = self.strings.getOffset(name) orelse return null; | |
| 5800 | return self.resolver.get(name_off); | |
| 5801 | } | |
| 5802 | ||
| 5803 | 5475 | pub fn getGlobalSymbol(self: *Elf, name: []const u8, lib_name: ?[]const u8) !u32 { |
| 5804 | 5476 | return self.zigObjectPtr().?.getGlobalSymbol(self, name, lib_name); |
| 5805 | 5477 | } |
| ... | ... | @@ -5809,69 +5481,12 @@ pub fn zigObjectPtr(self: *Elf) ?*ZigObject { |
| 5809 | 5481 | return self.file(index).?.zig_object; |
| 5810 | 5482 | } |
| 5811 | 5483 | |
| 5812 | const GetOrCreateComdatGroupOwnerResult = struct { | |
| 5813 | found_existing: bool, | |
| 5814 | index: ComdatGroupOwner.Index, | |
| 5815 | }; | |
| 5816 | ||
| 5817 | pub fn getOrCreateComdatGroupOwner(self: *Elf, name: [:0]const u8) !GetOrCreateComdatGroupOwnerResult { | |
| 5818 | const gpa = self.base.comp.gpa; | |
| 5819 | const off = try self.strings.insert(gpa, name); | |
| 5820 | const gop = try self.comdat_groups_table.getOrPut(gpa, off); | |
| 5821 | if (!gop.found_existing) { | |
| 5822 | const index: ComdatGroupOwner.Index = @intCast(self.comdat_groups_owners.items.len); | |
| 5823 | const owner = try self.comdat_groups_owners.addOne(gpa); | |
| 5824 | owner.* = .{}; | |
| 5825 | gop.value_ptr.* = index; | |
| 5826 | } | |
| 5827 | return .{ | |
| 5828 | .found_existing = gop.found_existing, | |
| 5829 | .index = gop.value_ptr.*, | |
| 5830 | }; | |
| 5831 | } | |
| 5832 | ||
| 5833 | pub fn addComdatGroup(self: *Elf) !ComdatGroup.Index { | |
| 5834 | const gpa = self.base.comp.gpa; | |
| 5835 | const index = @as(ComdatGroup.Index, @intCast(self.comdat_groups.items.len)); | |
| 5836 | _ = try self.comdat_groups.addOne(gpa); | |
| 5837 | return index; | |
| 5838 | } | |
| 5839 | ||
| 5840 | pub fn comdatGroup(self: *Elf, index: ComdatGroup.Index) *ComdatGroup { | |
| 5841 | assert(index < self.comdat_groups.items.len); | |
| 5842 | return &self.comdat_groups.items[index]; | |
| 5843 | } | |
| 5844 | ||
| 5845 | pub fn comdatGroupOwner(self: *Elf, index: ComdatGroupOwner.Index) *ComdatGroupOwner { | |
| 5846 | assert(index < self.comdat_groups_owners.items.len); | |
| 5847 | return &self.comdat_groups_owners.items[index]; | |
| 5484 | pub fn linkerDefinedPtr(self: *Elf) ?*LinkerDefined { | |
| 5485 | const index = self.linker_defined_index orelse return null; | |
| 5486 | return self.file(index).?.linker_defined; | |
| 5848 | 5487 | } |
| 5849 | 5488 | |
| 5850 | pub fn addInputMergeSection(self: *Elf) !InputMergeSection.Index { | |
| 5851 | const index: InputMergeSection.Index = @intCast(self.merge_input_sections.items.len); | |
| 5852 | const msec = try self.merge_input_sections.addOne(self.base.comp.gpa); | |
| 5853 | msec.* = .{}; | |
| 5854 | return index; | |
| 5855 | } | |
| 5856 | ||
| 5857 | pub fn inputMergeSection(self: *Elf, index: InputMergeSection.Index) ?*InputMergeSection { | |
| 5858 | if (index == 0) return null; | |
| 5859 | return &self.merge_input_sections.items[index]; | |
| 5860 | } | |
| 5861 | ||
| 5862 | pub fn addMergeSubsection(self: *Elf) !MergeSubsection.Index { | |
| 5863 | const index: MergeSubsection.Index = @intCast(self.merge_subsections.items.len); | |
| 5864 | const msec = try self.merge_subsections.addOne(self.base.comp.gpa); | |
| 5865 | msec.* = .{}; | |
| 5866 | return index; | |
| 5867 | } | |
| 5868 | ||
| 5869 | pub fn mergeSubsection(self: *Elf, index: MergeSubsection.Index) *MergeSubsection { | |
| 5870 | assert(index < self.merge_subsections.items.len); | |
| 5871 | return &self.merge_subsections.items[index]; | |
| 5872 | } | |
| 5873 | ||
| 5874 | pub fn getOrCreateMergeSection(self: *Elf, name: []const u8, flags: u64, @"type": u32) !MergeSection.Index { | |
| 5489 | pub fn getOrCreateMergeSection(self: *Elf, name: [:0]const u8, flags: u64, @"type": u32) !MergeSection.Index { | |
| 5875 | 5490 | const gpa = self.base.comp.gpa; |
| 5876 | 5491 | const out_name = name: { |
| 5877 | 5492 | if (self.base.isRelocatable()) break :name name; |
| ... | ... | @@ -5879,11 +5494,11 @@ pub fn getOrCreateMergeSection(self: *Elf, name: []const u8, flags: u64, @"type" |
| 5879 | 5494 | break :name if (flags & elf.SHF_STRINGS != 0) ".rodata.str" else ".rodata.cst"; |
| 5880 | 5495 | break :name name; |
| 5881 | 5496 | }; |
| 5882 | const out_off = try self.strings.insert(gpa, out_name); | |
| 5883 | const out_flags = flags & ~@as(u64, elf.SHF_COMPRESSED | elf.SHF_GROUP); | |
| 5884 | 5497 | for (self.merge_sections.items, 0..) |msec, index| { |
| 5885 | if (msec.name_offset == out_off) return @intCast(index); | |
| 5498 | if (mem.eql(u8, msec.name(self), out_name)) return @intCast(index); | |
| 5886 | 5499 | } |
| 5500 | const out_off = try self.insertShString(out_name); | |
| 5501 | const out_flags = flags & ~@as(u64, elf.SHF_COMPRESSED | elf.SHF_GROUP); | |
| 5887 | 5502 | const index = @as(MergeSection.Index, @intCast(self.merge_sections.items.len)); |
| 5888 | 5503 | const msec = try self.merge_sections.addOne(gpa); |
| 5889 | 5504 | msec.* = .{ |
| ... | ... | @@ -5974,9 +5589,9 @@ fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void { |
| 5974 | 5589 | var err = try self.base.addErrorWithNotesAssumeCapacity(nnotes); |
| 5975 | 5590 | try err.addMsg("undefined symbol: {s}", .{self.symbol(undef_index).name(self)}); |
| 5976 | 5591 | |
| 5977 | for (atoms[0..natoms]) |atom_index| { | |
| 5978 | const atom_ptr = self.atom(atom_index).?; | |
| 5979 | const file_ptr = self.file(atom_ptr.file_index).?; | |
| 5592 | for (atoms[0..natoms]) |ref| { | |
| 5593 | const atom_ptr = self.atom(ref).?; | |
| 5594 | const file_ptr = self.file(ref.file).?; | |
| 5980 | 5595 | try err.addNote("referenced by {s}:{s}", .{ file_ptr.fmtPath(), atom_ptr.name(self) }); |
| 5981 | 5596 | } |
| 5982 | 5597 | |
| ... | ... | @@ -6253,7 +5868,7 @@ fn fmtDumpState( |
| 6253 | 5868 | |
| 6254 | 5869 | try writer.writeAll("Output COMDAT groups\n"); |
| 6255 | 5870 | for (self.comdat_group_sections.items) |cg| { |
| 6256 | try writer.print(" shdr({d}) : COMDAT({d})\n", .{ cg.shndx, cg.cg_index }); | |
| 5871 | try writer.print(" shdr({d}) : COMDAT({})\n", .{ cg.shndx, cg.cg_ref }); | |
| 6257 | 5872 | } |
| 6258 | 5873 | |
| 6259 | 5874 | try writer.writeAll("\nOutput merge sections\n"); |
| ... | ... | @@ -6340,21 +5955,24 @@ const default_entry_addr = 0x8000000; |
| 6340 | 5955 | |
| 6341 | 5956 | pub const base_tag: link.File.Tag = .elf; |
| 6342 | 5957 | |
| 6343 | const ComdatGroupOwner = struct { | |
| 6344 | file: File.Index = 0, | |
| 6345 | ||
| 6346 | const Index = u32; | |
| 6347 | }; | |
| 6348 | ||
| 6349 | 5958 | pub const ComdatGroup = struct { |
| 6350 | owner: ComdatGroupOwner.Index, | |
| 6351 | file: File.Index, | |
| 5959 | signature_off: u32, | |
| 5960 | file_index: File.Index, | |
| 6352 | 5961 | shndx: u32, |
| 6353 | 5962 | members_start: u32, |
| 6354 | 5963 | members_len: u32, |
| 5964 | alive: bool = true, | |
| 5965 | ||
| 5966 | pub fn file(cg: ComdatGroup, elf_file: *Elf) File { | |
| 5967 | return elf_file.file(cg.file_index).?; | |
| 5968 | } | |
| 5969 | ||
| 5970 | pub fn signature(cg: ComdatGroup, elf_file: *Elf) [:0]const u8 { | |
| 5971 | return cg.file(elf_file).object.getString(cg.signature_off); | |
| 5972 | } | |
| 6355 | 5973 | |
| 6356 | 5974 | pub fn comdatGroupMembers(cg: ComdatGroup, elf_file: *Elf) []const u32 { |
| 6357 | const object = elf_file.file(cg.file).?.object; | |
| 5975 | const object = cg.file(elf_file).object; | |
| 6358 | 5976 | return object.comdat_group_data.items[cg.members_start..][0..cg.members_len]; |
| 6359 | 5977 | } |
| 6360 | 5978 | |
| ... | ... | @@ -6396,6 +6014,22 @@ pub const SystemLib = struct { |
| 6396 | 6014 | path: []const u8, |
| 6397 | 6015 | }; |
| 6398 | 6016 | |
| 6017 | pub const Ref = struct { | |
| 6018 | index: u32, | |
| 6019 | file: u32, | |
| 6020 | ||
| 6021 | pub fn format( | |
| 6022 | ref: Ref, | |
| 6023 | comptime unused_fmt_string: []const u8, | |
| 6024 | options: std.fmt.FormatOptions, | |
| 6025 | writer: anytype, | |
| 6026 | ) !void { | |
| 6027 | _ = unused_fmt_string; | |
| 6028 | _ = options; | |
| 6029 | try writer.print("ref({},{})", .{ ref.index, ref.file }); | |
| 6030 | } | |
| 6031 | }; | |
| 6032 | ||
| 6399 | 6033 | const LastAtomAndFreeList = struct { |
| 6400 | 6034 | /// Index of the last allocated atom in this section. |
| 6401 | 6035 | last_atom_index: Atom.Index = 0, |
| ... | ... | @@ -6421,7 +6055,7 @@ const LastAtomAndFreeListTable = std.AutoArrayHashMapUnmanaged(u32, LastAtomAndF |
| 6421 | 6055 | |
| 6422 | 6056 | const RelaSection = struct { |
| 6423 | 6057 | shndx: u32, |
| 6424 | atom_list: std.ArrayListUnmanaged(Atom.Index) = .{}, | |
| 6058 | atom_list: std.ArrayListUnmanaged(Ref) = .{}, | |
| 6425 | 6059 | }; |
| 6426 | 6060 | const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection); |
| 6427 | 6061 |
src/link/Elf/Atom.zig+54-68| ... | ... | @@ -30,14 +30,17 @@ atom_index: Index = 0, |
| 30 | 30 | prev_index: Index = 0, |
| 31 | 31 | next_index: Index = 0, |
| 32 | 32 | |
| 33 | /// Flags we use for state tracking. | |
| 34 | flags: Flags = .{}, | |
| 33 | /// Specifies whether this atom is alive or has been garbage collected. | |
| 34 | alive: bool = true, | |
| 35 | ||
| 36 | /// Specifies if the atom has been visited during garbage collection. | |
| 37 | visited: bool = false, | |
| 35 | 38 | |
| 36 | 39 | extra_index: u32 = 0, |
| 37 | 40 | |
| 38 | 41 | pub const Alignment = @import("../../InternPool.zig").Alignment; |
| 39 | 42 | |
| 40 | pub fn name(self: Atom, elf_file: *Elf) []const u8 { | |
| 43 | pub fn name(self: Atom, elf_file: *Elf) [:0]const u8 { | |
| 41 | 44 | const file_ptr = self.file(elf_file).?; |
| 42 | 45 | return switch (file_ptr) { |
| 43 | 46 | inline else => |x| x.getString(self.name_offset), |
| ... | ... | @@ -45,8 +48,7 @@ pub fn name(self: Atom, elf_file: *Elf) []const u8 { |
| 45 | 48 | } |
| 46 | 49 | |
| 47 | 50 | pub fn address(self: Atom, elf_file: *Elf) i64 { |
| 48 | const shndx = self.outputShndx() orelse return self.value; | |
| 49 | const shdr = elf_file.shdrs.items[shndx]; | |
| 51 | const shdr = elf_file.shdrs.items[self.output_section_index]; | |
| 50 | 52 | return @as(i64, @intCast(shdr.sh_addr)) + self.value; |
| 51 | 53 | } |
| 52 | 54 | |
| ... | ... | @@ -55,7 +57,7 @@ pub fn debugTombstoneValue(self: Atom, target: Symbol, elf_file: *Elf) ?u64 { |
| 55 | 57 | if (msub.alive) return null; |
| 56 | 58 | } |
| 57 | 59 | if (target.atom(elf_file)) |atom_ptr| { |
| 58 | if (atom_ptr.flags.alive) return null; | |
| 60 | if (atom_ptr.alive) return null; | |
| 59 | 61 | } |
| 60 | 62 | const atom_name = self.name(elf_file); |
| 61 | 63 | if (!mem.startsWith(u8, atom_name, ".debug")) return null; |
| ... | ... | @@ -67,8 +69,7 @@ pub fn file(self: Atom, elf_file: *Elf) ?File { |
| 67 | 69 | } |
| 68 | 70 | |
| 69 | 71 | pub fn thunk(self: Atom, elf_file: *Elf) *Thunk { |
| 70 | assert(self.flags.thunk); | |
| 71 | const extras = self.extra(elf_file).?; | |
| 72 | const extras = self.extra(elf_file); | |
| 72 | 73 | return elf_file.thunk(extras.thunk); |
| 73 | 74 | } |
| 74 | 75 | |
| ... | ... | @@ -85,11 +86,6 @@ pub fn relocsShndx(self: Atom) ?u32 { |
| 85 | 86 | return self.relocs_section_index; |
| 86 | 87 | } |
| 87 | 88 | |
| 88 | pub fn outputShndx(self: Atom) ?u32 { | |
| 89 | if (self.output_section_index == 0) return null; | |
| 90 | return self.output_section_index; | |
| 91 | } | |
| 92 | ||
| 93 | 89 | pub fn priority(self: Atom, elf_file: *Elf) u64 { |
| 94 | 90 | const index = self.file(elf_file).?.index(); |
| 95 | 91 | return (@as(u64, @intCast(index)) << 32) | @as(u64, @intCast(self.input_section_index)); |
| ... | ... | @@ -99,7 +95,8 @@ pub fn priority(self: Atom, elf_file: *Elf) u64 { |
| 99 | 95 | /// File offset relocation happens transparently, so it is not included in |
| 100 | 96 | /// this calculation. |
| 101 | 97 | pub fn capacity(self: Atom, elf_file: *Elf) u64 { |
| 102 | const next_addr = if (elf_file.atom(self.next_index)) |next| | |
| 98 | const zo = elf_file.zigObjectPtr().?; | |
| 99 | const next_addr = if (zo.atom(self.next_index)) |next| | |
| 103 | 100 | next.address(elf_file) |
| 104 | 101 | else |
| 105 | 102 | std.math.maxInt(u32); |
| ... | ... | @@ -107,8 +104,9 @@ pub fn capacity(self: Atom, elf_file: *Elf) u64 { |
| 107 | 104 | } |
| 108 | 105 | |
| 109 | 106 | pub fn freeListEligible(self: Atom, elf_file: *Elf) bool { |
| 107 | const zo = elf_file.zigObjectPtr().?; | |
| 110 | 108 | // No need to keep a free list node for the last block. |
| 111 | const next = elf_file.atom(self.next_index) orelse return false; | |
| 109 | const next = zo.atom(self.next_index) orelse return false; | |
| 112 | 110 | const cap: u64 = @intCast(next.address(elf_file) - self.address(elf_file)); |
| 113 | 111 | const ideal_cap = Elf.padToIdeal(self.size); |
| 114 | 112 | if (cap <= ideal_cap) return false; |
| ... | ... | @@ -117,8 +115,9 @@ pub fn freeListEligible(self: Atom, elf_file: *Elf) bool { |
| 117 | 115 | } |
| 118 | 116 | |
| 119 | 117 | pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 120 | const shdr = &elf_file.shdrs.items[self.outputShndx().?]; | |
| 121 | const meta = elf_file.last_atom_and_free_list_table.getPtr(self.outputShndx().?).?; | |
| 118 | const zo = elf_file.zigObjectPtr().?; | |
| 119 | const shdr = &elf_file.shdrs.items[self.output_section_index]; | |
| 120 | const meta = elf_file.last_atom_and_free_list_table.getPtr(self.output_section_index).?; | |
| 122 | 121 | const free_list = &meta.free_list; |
| 123 | 122 | const last_atom_index = &meta.last_atom_index; |
| 124 | 123 | const new_atom_ideal_capacity = Elf.padToIdeal(self.size); |
| ... | ... | @@ -137,7 +136,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 137 | 136 | var i: usize = if (elf_file.base.child_pid == null) 0 else free_list.items.len; |
| 138 | 137 | while (i < free_list.items.len) { |
| 139 | 138 | const big_atom_index = free_list.items[i]; |
| 140 | const big_atom = elf_file.atom(big_atom_index).?; | |
| 139 | const big_atom = zo.atom(big_atom_index).?; | |
| 141 | 140 | // We now have a pointer to a live atom that has too much capacity. |
| 142 | 141 | // Is it enough that we could fit this new atom? |
| 143 | 142 | const cap = big_atom.capacity(elf_file); |
| ... | ... | @@ -169,7 +168,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 169 | 168 | free_list_removal = i; |
| 170 | 169 | } |
| 171 | 170 | break :blk @intCast(new_start_vaddr); |
| 172 | } else if (elf_file.atom(last_atom_index.*)) |last| { | |
| 171 | } else if (zo.atom(last_atom_index.*)) |last| { | |
| 173 | 172 | const ideal_capacity = Elf.padToIdeal(last.size); |
| 174 | 173 | const ideal_capacity_end_vaddr = @as(u64, @intCast(last.value)) + ideal_capacity; |
| 175 | 174 | const new_start_vaddr = self.alignment.forward(ideal_capacity_end_vaddr); |
| ... | ... | @@ -189,12 +188,12 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 189 | 188 | }); |
| 190 | 189 | |
| 191 | 190 | const expand_section = if (atom_placement) |placement_index| |
| 192 | elf_file.atom(placement_index).?.next_index == 0 | |
| 191 | zo.atom(placement_index).?.next_index == 0 | |
| 193 | 192 | else |
| 194 | 193 | true; |
| 195 | 194 | if (expand_section) { |
| 196 | 195 | const needed_size: u64 = @intCast(self.value + @as(i64, @intCast(self.size))); |
| 197 | try elf_file.growAllocSection(self.outputShndx().?, needed_size); | |
| 196 | try elf_file.growAllocSection(self.output_section_index, needed_size); | |
| 198 | 197 | last_atom_index.* = self.atom_index; |
| 199 | 198 | |
| 200 | 199 | const zig_object = elf_file.zigObjectPtr().?; |
| ... | ... | @@ -214,15 +213,15 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 214 | 213 | // This function can also reallocate an atom. |
| 215 | 214 | // In this case we need to "unplug" it from its previous location before |
| 216 | 215 | // plugging it in to its new location. |
| 217 | if (elf_file.atom(self.prev_index)) |prev| { | |
| 216 | if (zo.atom(self.prev_index)) |prev| { | |
| 218 | 217 | prev.next_index = self.next_index; |
| 219 | 218 | } |
| 220 | if (elf_file.atom(self.next_index)) |next| { | |
| 219 | if (zo.atom(self.next_index)) |next| { | |
| 221 | 220 | next.prev_index = self.prev_index; |
| 222 | 221 | } |
| 223 | 222 | |
| 224 | 223 | if (atom_placement) |big_atom_index| { |
| 225 | const big_atom = elf_file.atom(big_atom_index).?; | |
| 224 | const big_atom = zo.atom(big_atom_index).?; | |
| 226 | 225 | self.prev_index = big_atom_index; |
| 227 | 226 | self.next_index = big_atom.next_index; |
| 228 | 227 | big_atom.next_index = self.atom_index; |
| ... | ... | @@ -234,7 +233,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 234 | 233 | _ = free_list.swapRemove(i); |
| 235 | 234 | } |
| 236 | 235 | |
| 237 | self.flags.alive = true; | |
| 236 | self.alive = true; | |
| 238 | 237 | } |
| 239 | 238 | |
| 240 | 239 | pub fn shrink(self: *Atom, elf_file: *Elf) void { |
| ... | ... | @@ -250,9 +249,10 @@ pub fn grow(self: *Atom, elf_file: *Elf) !void { |
| 250 | 249 | pub fn free(self: *Atom, elf_file: *Elf) void { |
| 251 | 250 | log.debug("freeAtom {d} ({s})", .{ self.atom_index, self.name(elf_file) }); |
| 252 | 251 | |
| 252 | const zo = elf_file.zigObjectPtr().?; | |
| 253 | 253 | const comp = elf_file.base.comp; |
| 254 | 254 | const gpa = comp.gpa; |
| 255 | const shndx = self.outputShndx().?; | |
| 255 | const shndx = self.output_section_index; | |
| 256 | 256 | const meta = elf_file.last_atom_and_free_list_table.getPtr(shndx).?; |
| 257 | 257 | const free_list = &meta.free_list; |
| 258 | 258 | const last_atom_index = &meta.last_atom_index; |
| ... | ... | @@ -272,9 +272,9 @@ pub fn free(self: *Atom, elf_file: *Elf) void { |
| 272 | 272 | } |
| 273 | 273 | } |
| 274 | 274 | |
| 275 | if (elf_file.atom(last_atom_index.*)) |last_atom| { | |
| 275 | if (zo.atom(last_atom_index.*)) |last_atom| { | |
| 276 | 276 | if (last_atom.atom_index == self.atom_index) { |
| 277 | if (elf_file.atom(self.prev_index)) |_| { | |
| 277 | if (zo.atom(self.prev_index)) |_| { | |
| 278 | 278 | // TODO shrink the section size here |
| 279 | 279 | last_atom_index.* = self.prev_index; |
| 280 | 280 | } else { |
| ... | ... | @@ -283,7 +283,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void { |
| 283 | 283 | } |
| 284 | 284 | } |
| 285 | 285 | |
| 286 | if (elf_file.atom(self.prev_index)) |prev| { | |
| 286 | if (zo.atom(self.prev_index)) |prev| { | |
| 287 | 287 | prev.next_index = self.next_index; |
| 288 | 288 | if (!already_have_free_list_node and prev.*.freeListEligible(elf_file)) { |
| 289 | 289 | // The free list is heuristics, it doesn't have to be perfect, so we can |
| ... | ... | @@ -294,7 +294,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void { |
| 294 | 294 | self.prev_index = 0; |
| 295 | 295 | } |
| 296 | 296 | |
| 297 | if (elf_file.atom(self.next_index)) |next| { | |
| 297 | if (zo.atom(self.next_index)) |next| { | |
| 298 | 298 | next.prev_index = self.prev_index; |
| 299 | 299 | } else { |
| 300 | 300 | self.next_index = 0; |
| ... | ... | @@ -313,7 +313,7 @@ pub fn relocs(self: Atom, elf_file: *Elf) []const elf.Elf64_Rela { |
| 313 | 313 | switch (self.file(elf_file).?) { |
| 314 | 314 | .zig_object => |x| return x.relocs.items[shndx].items, |
| 315 | 315 | .object => |x| { |
| 316 | const extras = self.extra(elf_file).?; | |
| 316 | const extras = self.extra(elf_file); | |
| 317 | 317 | return x.relocs.items[extras.rel_index..][0..extras.rel_count]; |
| 318 | 318 | }, |
| 319 | 319 | else => unreachable, |
| ... | ... | @@ -337,12 +337,12 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El |
| 337 | 337 | var r_addend = rel.r_addend; |
| 338 | 338 | var r_sym: u32 = 0; |
| 339 | 339 | switch (target.type(elf_file)) { |
| 340 | elf.STT_SECTION => if (target.mergeSubsection(elf_file)) |msub| { | |
| 341 | r_addend += @intCast(target.address(.{}, elf_file)); | |
| 342 | r_sym = elf_file.sectionSymbolOutputSymtabIndex(msub.mergeSection(elf_file).output_section_index); | |
| 343 | } else { | |
| 340 | elf.STT_SECTION => { | |
| 344 | 341 | r_addend += @intCast(target.address(.{}, elf_file)); |
| 345 | r_sym = elf_file.sectionSymbolOutputSymtabIndex(target.outputShndx().?); | |
| 342 | r_sym = if (target.outputShndx(elf_file)) |osec| | |
| 343 | elf_file.sectionSymbolOutputSymtabIndex(osec) | |
| 344 | else | |
| 345 | 0; | |
| 346 | 346 | }, |
| 347 | 347 | else => { |
| 348 | 348 | r_sym = target.outputSymtabIndex(elf_file) orelse 0; |
| ... | ... | @@ -366,10 +366,12 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El |
| 366 | 366 | } |
| 367 | 367 | |
| 368 | 368 | pub fn fdes(self: Atom, elf_file: *Elf) []Fde { |
| 369 | if (!self.flags.fde) return &[0]Fde{}; | |
| 370 | const extras = self.extra(elf_file).?; | |
| 371 | const object = self.file(elf_file).?.object; | |
| 372 | return object.fdes.items[extras.fde_start..][0..extras.fde_count]; | |
| 369 | const extras = self.extra(elf_file); | |
| 370 | return switch (self.file(elf_file).?) { | |
| 371 | .shared_object => unreachable, | |
| 372 | .linker_defined, .zig_object => &[0]Fde{}, | |
| 373 | .object => |x| x.fdes.items[extras.fde_start..][0..extras.fde_count], | |
| 374 | }; | |
| 373 | 375 | } |
| 374 | 376 | |
| 375 | 377 | pub fn markFdesDead(self: Atom, elf_file: *Elf) void { |
| ... | ... | @@ -712,9 +714,9 @@ fn reportUndefined( |
| 712 | 714 | { |
| 713 | 715 | const gop = try undefs.getOrPut(sym_index); |
| 714 | 716 | if (!gop.found_existing) { |
| 715 | gop.value_ptr.* = std.ArrayList(Atom.Index).init(gpa); | |
| 717 | gop.value_ptr.* = std.ArrayList(Elf.Ref).init(gpa); | |
| 716 | 718 | } |
| 717 | try gop.value_ptr.append(self.atom_index); | |
| 719 | try gop.value_ptr.append(.{ .index = self.atom_index, .file = self.file_index }); | |
| 718 | 720 | return true; |
| 719 | 721 | } |
| 720 | 722 | |
| ... | ... | @@ -1001,25 +1003,23 @@ const AddExtraOpts = struct { |
| 1001 | 1003 | rel_count: ?u32 = null, |
| 1002 | 1004 | }; |
| 1003 | 1005 | |
| 1004 | pub fn addExtra(atom: *Atom, opts: AddExtraOpts, elf_file: *Elf) !void { | |
| 1005 | if (atom.extra(elf_file) == null) { | |
| 1006 | atom.extra_index = try elf_file.addAtomExtra(.{}); | |
| 1007 | } | |
| 1008 | var extras = atom.extra(elf_file).?; | |
| 1006 | pub fn addExtra(atom: *Atom, opts: AddExtraOpts, elf_file: *Elf) void { | |
| 1007 | const file_ptr = atom.file(elf_file).?; | |
| 1008 | var extras = file_ptr.atomExtra(atom.extra_index); | |
| 1009 | 1009 | inline for (@typeInfo(@TypeOf(opts)).Struct.fields) |field| { |
| 1010 | 1010 | if (@field(opts, field.name)) |x| { |
| 1011 | 1011 | @field(extras, field.name) = x; |
| 1012 | 1012 | } |
| 1013 | 1013 | } |
| 1014 | atom.setExtra(extras, elf_file); | |
| 1014 | file_ptr.setAtomExtra(atom.extra_index, extras); | |
| 1015 | 1015 | } |
| 1016 | 1016 | |
| 1017 | pub inline fn extra(atom: Atom, elf_file: *Elf) ?Extra { | |
| 1018 | return elf_file.atomExtra(atom.extra_index); | |
| 1017 | pub inline fn extra(atom: Atom, elf_file: *Elf) Extra { | |
| 1018 | return atom.file(elf_file).?.atomExtra(atom.extra_index); | |
| 1019 | 1019 | } |
| 1020 | 1020 | |
| 1021 | 1021 | pub inline fn setExtra(atom: Atom, extras: Extra, elf_file: *Elf) void { |
| 1022 | elf_file.setAtomExtra(atom.extra_index, extras); | |
| 1022 | atom.file(elf_file).?.setAtomExtra(atom.extra_index, extras); | |
| 1023 | 1023 | } |
| 1024 | 1024 | |
| 1025 | 1025 | pub fn format( |
| ... | ... | @@ -1061,9 +1061,9 @@ fn format2( |
| 1061 | 1061 | atom.atom_index, atom.name(elf_file), atom.address(elf_file), |
| 1062 | 1062 | atom.output_section_index, atom.alignment, atom.size, |
| 1063 | 1063 | }); |
| 1064 | if (atom.flags.fde) { | |
| 1064 | if (atom.fdes(elf_file).len > 0) { | |
| 1065 | 1065 | try writer.writeAll(" : fdes{ "); |
| 1066 | const extras = atom.extra(elf_file).?; | |
| 1066 | const extras = atom.extra(elf_file); | |
| 1067 | 1067 | for (atom.fdes(elf_file), extras.fde_start..) |fde, i| { |
| 1068 | 1068 | try writer.print("{d}", .{i}); |
| 1069 | 1069 | if (!fde.alive) try writer.writeAll("([*])"); |
| ... | ... | @@ -1071,27 +1071,13 @@ fn format2( |
| 1071 | 1071 | } |
| 1072 | 1072 | try writer.writeAll(" }"); |
| 1073 | 1073 | } |
| 1074 | if (!atom.flags.alive) { | |
| 1074 | if (!atom.alive) { | |
| 1075 | 1075 | try writer.writeAll(" : [*]"); |
| 1076 | 1076 | } |
| 1077 | 1077 | } |
| 1078 | 1078 | |
| 1079 | 1079 | pub const Index = u32; |
| 1080 | 1080 | |
| 1081 | pub const Flags = packed struct { | |
| 1082 | /// Specifies whether this atom is alive or has been garbage collected. | |
| 1083 | alive: bool = true, | |
| 1084 | ||
| 1085 | /// Specifies if the atom has been visited during garbage collection. | |
| 1086 | visited: bool = false, | |
| 1087 | ||
| 1088 | /// Whether this atom has a range extension thunk. | |
| 1089 | thunk: bool = false, | |
| 1090 | ||
| 1091 | /// Whether this atom has FDE records. | |
| 1092 | fde: bool = false, | |
| 1093 | }; | |
| 1094 | ||
| 1095 | 1081 | const x86_64 = struct { |
| 1096 | 1082 | fn scanReloc( |
| 1097 | 1083 | atom: Atom, |
src/link/Elf/LinkerDefined.zig+223-2| ... | ... | @@ -1,17 +1,89 @@ |
| 1 | 1 | index: File.Index, |
| 2 | ||
| 2 | 3 | symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{}, |
| 3 | 4 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 4 | 5 | symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 5 | 6 | |
| 7 | entry_index: ?Symbol.Index = null, | |
| 8 | dynamic_index: ?Symbol.Index = null, | |
| 9 | ehdr_start_index: ?Symbol.Index = null, | |
| 10 | init_array_start_index: ?Symbol.Index = null, | |
| 11 | init_array_end_index: ?Symbol.Index = null, | |
| 12 | fini_array_start_index: ?Symbol.Index = null, | |
| 13 | fini_array_end_index: ?Symbol.Index = null, | |
| 14 | preinit_array_start_index: ?Symbol.Index = null, | |
| 15 | preinit_array_end_index: ?Symbol.Index = null, | |
| 16 | got_index: ?Symbol.Index = null, | |
| 17 | plt_index: ?Symbol.Index = null, | |
| 18 | end_index: ?Symbol.Index = null, | |
| 19 | gnu_eh_frame_hdr_index: ?Symbol.Index = null, | |
| 20 | dso_handle_index: ?Symbol.Index = null, | |
| 21 | rela_iplt_start_index: ?Symbol.Index = null, | |
| 22 | rela_iplt_end_index: ?Symbol.Index = null, | |
| 23 | global_pointer_index: ?Symbol.Index = null, | |
| 24 | start_stop_indexes: std.ArrayListUnmanaged(u32) = .{}, | |
| 25 | ||
| 6 | 26 | output_symtab_ctx: Elf.SymtabCtx = .{}, |
| 7 | 27 | |
| 8 | 28 | pub fn deinit(self: *LinkerDefined, allocator: Allocator) void { |
| 9 | 29 | self.symtab.deinit(allocator); |
| 10 | 30 | self.strtab.deinit(allocator); |
| 11 | 31 | self.symbols.deinit(allocator); |
| 32 | self.start_stop_indexes.deinit(allocator); | |
| 33 | } | |
| 34 | ||
| 35 | pub fn init(self: *LinkerDefined, allocator: Allocator) !void { | |
| 36 | // Null byte in strtab | |
| 37 | try self.strtab.append(allocator, 0); | |
| 12 | 38 | } |
| 13 | 39 | |
| 14 | pub fn addGlobal(self: *LinkerDefined, name: [:0]const u8, elf_file: *Elf) !u32 { | |
| 40 | pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void { | |
| 41 | const gpa = elf_file.base.comp.gpa; | |
| 42 | ||
| 43 | if (elf_file.entry_name) |name| { | |
| 44 | self.entry_index = try self.addGlobal(name, elf_file); | |
| 45 | } | |
| 46 | ||
| 47 | self.dynamic_index = try self.addGlobal("_DYNAMIC", elf_file); | |
| 48 | self.ehdr_start_index = try self.addGlobal("__ehdr_start", elf_file); | |
| 49 | self.init_array_start_index = try self.addGlobal("__init_array_start", elf_file); | |
| 50 | self.init_array_end_index = try self.addGlobal("__init_array_end", elf_file); | |
| 51 | self.fini_array_start_index = try self.addGlobal("__fini_array_start", elf_file); | |
| 52 | self.fini_array_end_index = try self.addGlobal("__fini_array_end", elf_file); | |
| 53 | self.preinit_array_start_index = try self.addGlobal("__preinit_array_start", elf_file); | |
| 54 | self.preinit_array_end_index = try self.addGlobal("__preinit_array_end", elf_file); | |
| 55 | self.got_index = try self.addGlobal("_GLOBAL_OFFSET_TABLE_", elf_file); | |
| 56 | self.plt_index = try self.addGlobal("_PROCEDURE_LINKAGE_TABLE_", elf_file); | |
| 57 | self.end_index = try self.addGlobal("_end", elf_file); | |
| 58 | ||
| 59 | if (elf_file.base.comp.link_eh_frame_hdr) { | |
| 60 | self.gnu_eh_frame_hdr_index = try self.addGlobal("__GNU_EH_FRAME_HDR", elf_file); | |
| 61 | } | |
| 62 | ||
| 63 | self.dso_handle_index = try self.addGlobal("__dso_handle", elf_file); | |
| 64 | self.rela_iplt_start_index = try self.addGlobal("__rela_iplt_start", elf_file); | |
| 65 | self.rela_iplt_end_index = try self.addGlobal("__rela_iplt_end", elf_file); | |
| 66 | ||
| 67 | for (elf_file.shdrs.items) |shdr| { | |
| 68 | if (elf_file.getStartStopBasename(shdr)) |name| { | |
| 69 | try self.start_stop_indexes.ensureUnusedCapacity(gpa, 2); | |
| 70 | ||
| 71 | const start = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name}); | |
| 72 | defer gpa.free(start); | |
| 73 | const stop = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name}); | |
| 74 | defer gpa.free(stop); | |
| 75 | ||
| 76 | self.start_stop_indexes.appendAssumeCapacity(try self.addGlobal(start, elf_file)); | |
| 77 | self.start_stop_indexes.appendAssumeCapacity(try self.addGlobal(stop, elf_file)); | |
| 78 | } | |
| 79 | } | |
| 80 | ||
| 81 | if (elf_file.getTarget().cpu.arch.isRISCV() and elf_file.isEffectivelyDynLib()) { | |
| 82 | self.global_pointer_index = try self.addGlobal("__global_pointer$", elf_file); | |
| 83 | } | |
| 84 | } | |
| 85 | ||
| 86 | fn addGlobal(self: *LinkerDefined, name: []const u8, elf_file: *Elf) !u32 { | |
| 15 | 87 | const comp = elf_file.base.comp; |
| 16 | 88 | const gpa = comp.gpa; |
| 17 | 89 | try self.symtab.ensureUnusedCapacity(gpa, 1); |
| ... | ... | @@ -41,7 +113,7 @@ pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) void { |
| 41 | 113 | const global = elf_file.symbol(index); |
| 42 | 114 | if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) { |
| 43 | 115 | global.value = 0; |
| 44 | global.atom_index = 0; | |
| 116 | global.ref = .{ .index = 0, .file = 0 }; | |
| 45 | 117 | global.file_index = self.index; |
| 46 | 118 | global.esym_index = sym_idx; |
| 47 | 119 | global.version_index = elf_file.default_sym_version; |
| ... | ... | @@ -49,6 +121,154 @@ pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) void { |
| 49 | 121 | } |
| 50 | 122 | } |
| 51 | 123 | |
| 124 | pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { | |
| 125 | const comp = elf_file.base.comp; | |
| 126 | const link_mode = comp.config.link_mode; | |
| 127 | ||
| 128 | // _DYNAMIC | |
| 129 | if (elf_file.dynamic_section_index) |shndx| { | |
| 130 | const shdr = &elf_file.shdrs.items[shndx]; | |
| 131 | const symbol_ptr = elf_file.symbol(self.dynamic_index.?); | |
| 132 | symbol_ptr.value = @intCast(shdr.sh_addr); | |
| 133 | symbol_ptr.output_section_index = shndx; | |
| 134 | } | |
| 135 | ||
| 136 | // __ehdr_start | |
| 137 | { | |
| 138 | const symbol_ptr = elf_file.symbol(self.ehdr_start_index.?); | |
| 139 | symbol_ptr.value = @intCast(elf_file.image_base); | |
| 140 | symbol_ptr.output_section_index = 1; | |
| 141 | } | |
| 142 | ||
| 143 | // __init_array_start, __init_array_end | |
| 144 | if (elf_file.sectionByName(".init_array")) |shndx| { | |
| 145 | const start_sym = elf_file.symbol(self.init_array_start_index.?); | |
| 146 | const end_sym = elf_file.symbol(self.init_array_end_index.?); | |
| 147 | const shdr = &elf_file.shdrs.items[shndx]; | |
| 148 | start_sym.output_section_index = shndx; | |
| 149 | start_sym.value = @intCast(shdr.sh_addr); | |
| 150 | end_sym.output_section_index = shndx; | |
| 151 | end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size); | |
| 152 | } | |
| 153 | ||
| 154 | // __fini_array_start, __fini_array_end | |
| 155 | if (elf_file.sectionByName(".fini_array")) |shndx| { | |
| 156 | const start_sym = elf_file.symbol(self.fini_array_start_index.?); | |
| 157 | const end_sym = elf_file.symbol(self.fini_array_end_index.?); | |
| 158 | const shdr = &elf_file.shdrs.items[shndx]; | |
| 159 | start_sym.output_section_index = shndx; | |
| 160 | start_sym.value = @intCast(shdr.sh_addr); | |
| 161 | end_sym.output_section_index = shndx; | |
| 162 | end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size); | |
| 163 | } | |
| 164 | ||
| 165 | // __preinit_array_start, __preinit_array_end | |
| 166 | if (elf_file.sectionByName(".preinit_array")) |shndx| { | |
| 167 | const start_sym = elf_file.symbol(self.preinit_array_start_index.?); | |
| 168 | const end_sym = elf_file.symbol(self.preinit_array_end_index.?); | |
| 169 | const shdr = &elf_file.shdrs.items[shndx]; | |
| 170 | start_sym.output_section_index = shndx; | |
| 171 | start_sym.value = @intCast(shdr.sh_addr); | |
| 172 | end_sym.output_section_index = shndx; | |
| 173 | end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size); | |
| 174 | } | |
| 175 | ||
| 176 | // _GLOBAL_OFFSET_TABLE_ | |
| 177 | if (elf_file.getTarget().cpu.arch == .x86_64) { | |
| 178 | if (elf_file.got_plt_section_index) |shndx| { | |
| 179 | const shdr = elf_file.shdrs.items[shndx]; | |
| 180 | const sym = elf_file.symbol(self.got_index.?); | |
| 181 | sym.value = @intCast(shdr.sh_addr); | |
| 182 | sym.output_section_index = shndx; | |
| 183 | } | |
| 184 | } else { | |
| 185 | if (elf_file.got_section_index) |shndx| { | |
| 186 | const shdr = elf_file.shdrs.items[shndx]; | |
| 187 | const sym = elf_file.symbol(self.got_index.?); | |
| 188 | sym.value = @intCast(shdr.sh_addr); | |
| 189 | sym.output_section_index = shndx; | |
| 190 | } | |
| 191 | } | |
| 192 | ||
| 193 | // _PROCEDURE_LINKAGE_TABLE_ | |
| 194 | if (elf_file.plt_section_index) |shndx| { | |
| 195 | const shdr = &elf_file.shdrs.items[shndx]; | |
| 196 | const symbol_ptr = elf_file.symbol(self.plt_index.?); | |
| 197 | symbol_ptr.value = @intCast(shdr.sh_addr); | |
| 198 | symbol_ptr.output_section_index = shndx; | |
| 199 | } | |
| 200 | ||
| 201 | // __dso_handle | |
| 202 | if (self.dso_handle_index) |index| { | |
| 203 | const shdr = &elf_file.shdrs.items[1]; | |
| 204 | const symbol_ptr = elf_file.symbol(index); | |
| 205 | symbol_ptr.value = @intCast(shdr.sh_addr); | |
| 206 | symbol_ptr.output_section_index = 0; | |
| 207 | } | |
| 208 | ||
| 209 | // __GNU_EH_FRAME_HDR | |
| 210 | if (elf_file.eh_frame_hdr_section_index) |shndx| { | |
| 211 | const shdr = &elf_file.shdrs.items[shndx]; | |
| 212 | const symbol_ptr = elf_file.symbol(self.gnu_eh_frame_hdr_index.?); | |
| 213 | symbol_ptr.value = @intCast(shdr.sh_addr); | |
| 214 | symbol_ptr.output_section_index = shndx; | |
| 215 | } | |
| 216 | ||
| 217 | // __rela_iplt_start, __rela_iplt_end | |
| 218 | if (elf_file.rela_dyn_section_index) |shndx| blk: { | |
| 219 | if (link_mode != .static or comp.config.pie) break :blk; | |
| 220 | const shdr = &elf_file.shdrs.items[shndx]; | |
| 221 | const end_addr = shdr.sh_addr + shdr.sh_size; | |
| 222 | const start_addr = end_addr - elf_file.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela); | |
| 223 | const start_sym = elf_file.symbol(self.rela_iplt_start_index.?); | |
| 224 | const end_sym = elf_file.symbol(self.rela_iplt_end_index.?); | |
| 225 | start_sym.value = @intCast(start_addr); | |
| 226 | start_sym.output_section_index = shndx; | |
| 227 | end_sym.value = @intCast(end_addr); | |
| 228 | end_sym.output_section_index = shndx; | |
| 229 | } | |
| 230 | ||
| 231 | // _end | |
| 232 | { | |
| 233 | const end_symbol = elf_file.symbol(self.end_index.?); | |
| 234 | for (elf_file.shdrs.items, 0..) |shdr, shndx| { | |
| 235 | if (shdr.sh_flags & elf.SHF_ALLOC != 0) { | |
| 236 | end_symbol.value = @intCast(shdr.sh_addr + shdr.sh_size); | |
| 237 | end_symbol.output_section_index = @intCast(shndx); | |
| 238 | } | |
| 239 | } | |
| 240 | } | |
| 241 | ||
| 242 | // __start_*, __stop_* | |
| 243 | { | |
| 244 | var index: usize = 0; | |
| 245 | while (index < self.start_stop_indexes.items.len) : (index += 2) { | |
| 246 | const start = elf_file.symbol(self.start_stop_indexes.items[index]); | |
| 247 | const name = start.name(elf_file); | |
| 248 | const stop = elf_file.symbol(self.start_stop_indexes.items[index + 1]); | |
| 249 | const shndx = elf_file.sectionByName(name["__start_".len..]).?; | |
| 250 | const shdr = &elf_file.shdrs.items[shndx]; | |
| 251 | start.value = @intCast(shdr.sh_addr); | |
| 252 | start.output_section_index = shndx; | |
| 253 | stop.value = @intCast(shdr.sh_addr + shdr.sh_size); | |
| 254 | stop.output_section_index = shndx; | |
| 255 | } | |
| 256 | } | |
| 257 | ||
| 258 | // __global_pointer$ | |
| 259 | if (self.global_pointer_index) |index| { | |
| 260 | const sym = elf_file.symbol(index); | |
| 261 | if (elf_file.sectionByName(".sdata")) |shndx| { | |
| 262 | const shdr = elf_file.shdrs.items[shndx]; | |
| 263 | sym.value = @intCast(shdr.sh_addr + 0x800); | |
| 264 | sym.output_section_index = shndx; | |
| 265 | } else { | |
| 266 | sym.value = 0; | |
| 267 | sym.output_section_index = 0; | |
| 268 | } | |
| 269 | } | |
| 270 | } | |
| 271 | ||
| 52 | 272 | pub fn globals(self: LinkerDefined) []const Symbol.Index { |
| 53 | 273 | return self.symbols.items; |
| 54 | 274 | } |
| ... | ... | @@ -127,6 +347,7 @@ const mem = std.mem; |
| 127 | 347 | const std = @import("std"); |
| 128 | 348 | |
| 129 | 349 | const Allocator = mem.Allocator; |
| 350 | const Atom = @import("Atom.zig"); | |
| 130 | 351 | const Elf = @import("../Elf.zig"); |
| 131 | 352 | const File = @import("file.zig").File; |
| 132 | 353 | const LinkerDefined = @This(); |
src/link/Elf/Object.zig+333-200| ... | ... | @@ -10,12 +10,17 @@ symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{}, |
| 10 | 10 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 11 | 11 | first_global: ?Symbol.Index = null, |
| 12 | 12 | symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 13 | atoms: std.ArrayListUnmanaged(Atom.Index) = .{}, | |
| 14 | comdat_groups: std.ArrayListUnmanaged(Elf.ComdatGroup.Index) = .{}, | |
| 15 | comdat_group_data: std.ArrayListUnmanaged(u32) = .{}, | |
| 16 | 13 | relocs: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{}, |
| 17 | 14 | |
| 18 | merge_sections: std.ArrayListUnmanaged(InputMergeSection.Index) = .{}, | |
| 15 | atoms: std.ArrayListUnmanaged(Atom) = .{}, | |
| 16 | atoms_indexes: std.ArrayListUnmanaged(Atom.Index) = .{}, | |
| 17 | atoms_extra: std.ArrayListUnmanaged(u32) = .{}, | |
| 18 | ||
| 19 | comdat_groups: std.ArrayListUnmanaged(Elf.ComdatGroup) = .{}, | |
| 20 | comdat_group_data: std.ArrayListUnmanaged(u32) = .{}, | |
| 21 | ||
| 22 | input_merge_sections: std.ArrayListUnmanaged(InputMergeSection) = .{}, | |
| 23 | input_merge_sections_indexes: std.ArrayListUnmanaged(InputMergeSection.Index) = .{}, | |
| 19 | 24 | |
| 20 | 25 | fdes: std.ArrayListUnmanaged(Fde) = .{}, |
| 21 | 26 | cies: std.ArrayListUnmanaged(Cie) = .{}, |
| ... | ... | @@ -47,13 +52,19 @@ pub fn deinit(self: *Object, allocator: Allocator) void { |
| 47 | 52 | self.strtab.deinit(allocator); |
| 48 | 53 | self.symbols.deinit(allocator); |
| 49 | 54 | self.atoms.deinit(allocator); |
| 55 | self.atoms_indexes.deinit(allocator); | |
| 56 | self.atoms_extra.deinit(allocator); | |
| 50 | 57 | self.comdat_groups.deinit(allocator); |
| 51 | 58 | self.comdat_group_data.deinit(allocator); |
| 52 | 59 | self.relocs.deinit(allocator); |
| 53 | 60 | self.fdes.deinit(allocator); |
| 54 | 61 | self.cies.deinit(allocator); |
| 55 | 62 | self.eh_frame_data.deinit(allocator); |
| 56 | self.merge_sections.deinit(allocator); | |
| 63 | for (self.input_merge_sections.items) |*isec| { | |
| 64 | isec.deinit(allocator); | |
| 65 | } | |
| 66 | self.input_merge_sections.deinit(allocator); | |
| 67 | self.input_merge_sections_indexes.deinit(allocator); | |
| 57 | 68 | } |
| 58 | 69 | |
| 59 | 70 | pub fn parse(self: *Object, elf_file: *Elf) !void { |
| ... | ... | @@ -62,14 +73,20 @@ pub fn parse(self: *Object, elf_file: *Elf) !void { |
| 62 | 73 | const handle = elf_file.fileHandle(self.file_handle); |
| 63 | 74 | |
| 64 | 75 | try self.parseCommon(gpa, handle, elf_file); |
| 76 | ||
| 77 | // Append null input merge section | |
| 78 | try self.input_merge_sections.append(gpa, .{}); | |
| 79 | // Allocate atom index 0 to null atom | |
| 80 | try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) }); | |
| 81 | ||
| 65 | 82 | try self.initAtoms(gpa, handle, elf_file); |
| 66 | 83 | try self.initSymtab(gpa, elf_file); |
| 67 | 84 | |
| 68 | 85 | for (self.shdrs.items, 0..) |shdr, i| { |
| 69 | const atom = elf_file.atom(self.atoms.items[i]) orelse continue; | |
| 70 | if (!atom.flags.alive) continue; | |
| 86 | const atom_ptr = self.atom(self.atoms_indexes.items[i]) orelse continue; | |
| 87 | if (!atom_ptr.alive) continue; | |
| 71 | 88 | if ((cpu_arch == .x86_64 and shdr.sh_type == elf.SHT_X86_64_UNWIND) or |
| 72 | mem.eql(u8, atom.name(elf_file), ".eh_frame")) | |
| 89 | mem.eql(u8, atom_ptr.name(elf_file), ".eh_frame")) | |
| 73 | 90 | { |
| 74 | 91 | try self.parseEhFrame(gpa, handle, @as(u32, @intCast(i)), elf_file); |
| 75 | 92 | } |
| ... | ... | @@ -169,8 +186,11 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil |
| 169 | 186 | |
| 170 | 187 | fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: *Elf) !void { |
| 171 | 188 | const shdrs = self.shdrs.items; |
| 172 | try self.atoms.resize(allocator, shdrs.len); | |
| 173 | @memset(self.atoms.items, 0); | |
| 189 | try self.atoms.ensureTotalCapacityPrecise(allocator, shdrs.len); | |
| 190 | try self.atoms_extra.ensureTotalCapacityPrecise(allocator, shdrs.len * @sizeOf(Atom.Extra)); | |
| 191 | try self.atoms_indexes.ensureTotalCapacityPrecise(allocator, shdrs.len); | |
| 192 | try self.atoms_indexes.resize(allocator, shdrs.len); | |
| 193 | @memset(self.atoms_indexes.items, 0); | |
| 174 | 194 | |
| 175 | 195 | for (shdrs, 0..) |shdr, i| { |
| 176 | 196 | if (shdr.sh_flags & elf.SHF_EXCLUDE != 0 and |
| ... | ... | @@ -188,37 +208,53 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: |
| 188 | 208 | const group_signature = blk: { |
| 189 | 209 | if (group_info_sym.st_name == 0 and group_info_sym.st_type() == elf.STT_SECTION) { |
| 190 | 210 | const sym_shdr = shdrs[group_info_sym.st_shndx]; |
| 191 | break :blk self.getString(sym_shdr.sh_name); | |
| 211 | break :blk sym_shdr.sh_name; | |
| 192 | 212 | } |
| 193 | break :blk self.getString(group_info_sym.st_name); | |
| 213 | break :blk group_info_sym.st_name; | |
| 194 | 214 | }; |
| 195 | 215 | |
| 196 | 216 | const shndx = @as(u32, @intCast(i)); |
| 197 | 217 | const group_raw_data = try self.preadShdrContentsAlloc(allocator, handle, shndx); |
| 198 | 218 | defer allocator.free(group_raw_data); |
| 199 | const group_nmembers = @divExact(group_raw_data.len, @sizeOf(u32)); | |
| 219 | const group_nmembers = math.divExact(usize, group_raw_data.len, @sizeOf(u32)) catch { | |
| 220 | try elf_file.reportParseError2( | |
| 221 | self.index, | |
| 222 | "corrupt section group: not evenly divisible ", | |
| 223 | .{}, | |
| 224 | ); | |
| 225 | return error.MalformedObject; | |
| 226 | }; | |
| 227 | if (group_nmembers == 0) { | |
| 228 | try elf_file.reportParseError2( | |
| 229 | self.index, | |
| 230 | "corrupt section group: empty section", | |
| 231 | .{}, | |
| 232 | ); | |
| 233 | return error.MalformedObject; | |
| 234 | } | |
| 200 | 235 | const group_members = @as([*]align(1) const u32, @ptrCast(group_raw_data.ptr))[0..group_nmembers]; |
| 201 | 236 | |
| 202 | 237 | if (group_members[0] != elf.GRP_COMDAT) { |
| 203 | // TODO convert into an error | |
| 204 | log.debug("{}: unknown SHT_GROUP format", .{self.fmtPath()}); | |
| 205 | continue; | |
| 238 | try elf_file.reportParseError2( | |
| 239 | self.index, | |
| 240 | "corrupt section group: unknown SHT_GROUP format", | |
| 241 | .{}, | |
| 242 | ); | |
| 243 | return error.MalformedObject; | |
| 206 | 244 | } |
| 207 | 245 | |
| 208 | 246 | const group_start = @as(u32, @intCast(self.comdat_group_data.items.len)); |
| 209 | 247 | try self.comdat_group_data.appendUnalignedSlice(allocator, group_members[1..]); |
| 210 | 248 | |
| 211 | const gop = try elf_file.getOrCreateComdatGroupOwner(group_signature); | |
| 212 | const comdat_group_index = try elf_file.addComdatGroup(); | |
| 213 | const comdat_group = elf_file.comdatGroup(comdat_group_index); | |
| 249 | const comdat_group_index = try self.addComdatGroup(allocator); | |
| 250 | const comdat_group = self.comdatGroup(comdat_group_index); | |
| 214 | 251 | comdat_group.* = .{ |
| 215 | .owner = gop.index, | |
| 216 | .file = self.index, | |
| 252 | .signature_off = group_signature, | |
| 253 | .file_index = self.index, | |
| 217 | 254 | .shndx = shndx, |
| 218 | 255 | .members_start = group_start, |
| 219 | 256 | .members_len = @intCast(group_nmembers - 1), |
| 220 | 257 | }; |
| 221 | try self.comdat_groups.append(allocator, comdat_group_index); | |
| 222 | 258 | }, |
| 223 | 259 | |
| 224 | 260 | elf.SHT_SYMTAB_SHNDX => @panic("TODO SHT_SYMTAB_SHNDX"), |
| ... | ... | @@ -233,7 +269,19 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: |
| 233 | 269 | else => { |
| 234 | 270 | const shndx = @as(u32, @intCast(i)); |
| 235 | 271 | if (self.skipShdr(shndx, elf_file)) continue; |
| 236 | try self.addAtom(allocator, handle, shdr, shndx, elf_file); | |
| 272 | const size, const alignment = if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) blk: { | |
| 273 | const data = try self.preadShdrContentsAlloc(allocator, handle, shndx); | |
| 274 | defer allocator.free(data); | |
| 275 | const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*; | |
| 276 | break :blk .{ chdr.ch_size, Alignment.fromNonzeroByteUnits(chdr.ch_addralign) }; | |
| 277 | } else .{ shdr.sh_size, Alignment.fromNonzeroByteUnits(shdr.sh_addralign) }; | |
| 278 | const atom_index = self.addAtomAssumeCapacity(.{ | |
| 279 | .name = shdr.sh_name, | |
| 280 | .shndx = shndx, | |
| 281 | .size = size, | |
| 282 | .alignment = alignment, | |
| 283 | }); | |
| 284 | self.atoms_indexes.items[shndx] = atom_index; | |
| 237 | 285 | }, |
| 238 | 286 | } |
| 239 | 287 | } |
| ... | ... | @@ -241,14 +289,14 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: |
| 241 | 289 | // Parse relocs sections if any. |
| 242 | 290 | for (shdrs, 0..) |shdr, i| switch (shdr.sh_type) { |
| 243 | 291 | elf.SHT_REL, elf.SHT_RELA => { |
| 244 | const atom_index = self.atoms.items[shdr.sh_info]; | |
| 245 | if (elf_file.atom(atom_index)) |atom| { | |
| 292 | const atom_index = self.atoms_indexes.items[shdr.sh_info]; | |
| 293 | if (self.atom(atom_index)) |atom_ptr| { | |
| 246 | 294 | const relocs = try self.preadRelocsAlloc(allocator, handle, @intCast(i)); |
| 247 | 295 | defer allocator.free(relocs); |
| 248 | atom.relocs_section_index = @intCast(i); | |
| 296 | atom_ptr.relocs_section_index = @intCast(i); | |
| 249 | 297 | const rel_index: u32 = @intCast(self.relocs.items.len); |
| 250 | 298 | const rel_count: u32 = @intCast(relocs.len); |
| 251 | try atom.addExtra(.{ .rel_index = rel_index, .rel_count = rel_count }, elf_file); | |
| 299 | atom_ptr.addExtra(.{ .rel_index = rel_index, .rel_count = rel_count }, elf_file); | |
| 252 | 300 | try self.relocs.appendUnalignedSlice(allocator, relocs); |
| 253 | 301 | if (elf_file.getTarget().cpu.arch == .riscv64) { |
| 254 | 302 | sortRelocs(self.relocs.items[rel_index..][0..rel_count]); |
| ... | ... | @@ -259,27 +307,6 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: |
| 259 | 307 | }; |
| 260 | 308 | } |
| 261 | 309 | |
| 262 | fn addAtom(self: *Object, allocator: Allocator, handle: std.fs.File, shdr: elf.Elf64_Shdr, shndx: u32, elf_file: *Elf) !void { | |
| 263 | const atom_index = try elf_file.addAtom(); | |
| 264 | const atom = elf_file.atom(atom_index).?; | |
| 265 | atom.atom_index = atom_index; | |
| 266 | atom.name_offset = shdr.sh_name; | |
| 267 | atom.file_index = self.index; | |
| 268 | atom.input_section_index = shndx; | |
| 269 | self.atoms.items[shndx] = atom_index; | |
| 270 | ||
| 271 | if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) { | |
| 272 | const data = try self.preadShdrContentsAlloc(allocator, handle, shndx); | |
| 273 | defer allocator.free(data); | |
| 274 | const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*; | |
| 275 | atom.size = chdr.ch_size; | |
| 276 | atom.alignment = Alignment.fromNonzeroByteUnits(chdr.ch_addralign); | |
| 277 | } else { | |
| 278 | atom.size = shdr.sh_size; | |
| 279 | atom.alignment = Alignment.fromNonzeroByteUnits(shdr.sh_addralign); | |
| 280 | } | |
| 281 | } | |
| 282 | ||
| 283 | 310 | fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{OutOfMemory}!u32 { |
| 284 | 311 | const name = blk: { |
| 285 | 312 | const name = self.getString(shdr.sh_name); |
| ... | ... | @@ -327,7 +354,7 @@ fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{O |
| 327 | 354 | const out_shndx = elf_file.sectionByName(name) orelse try elf_file.addSection(.{ |
| 328 | 355 | .type = @"type", |
| 329 | 356 | .flags = flags, |
| 330 | .name = name, | |
| 357 | .name = try elf_file.insertShString(name), | |
| 331 | 358 | }); |
| 332 | 359 | return out_shndx; |
| 333 | 360 | } |
| ... | ... | @@ -359,8 +386,10 @@ fn initSymtab(self: *Object, allocator: Allocator, elf_file: *Elf) !void { |
| 359 | 386 | sym_ptr.value = @intCast(sym.st_value); |
| 360 | 387 | sym_ptr.name_offset = sym.st_name; |
| 361 | 388 | sym_ptr.esym_index = @as(u32, @intCast(i)); |
| 362 | sym_ptr.atom_index = if (sym.st_shndx == elf.SHN_ABS) 0 else self.atoms.items[sym.st_shndx]; | |
| 363 | 389 | sym_ptr.file_index = self.index; |
| 390 | if (sym.st_shndx != elf.SHN_ABS) { | |
| 391 | sym_ptr.ref = .{ .index = self.atoms_indexes.items[sym.st_shndx], .file = self.index }; | |
| 392 | } | |
| 364 | 393 | } |
| 365 | 394 | |
| 366 | 395 | for (self.symtab.items[first_global..]) |sym| { |
| ... | ... | @@ -447,15 +476,14 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx: |
| 447 | 476 | var i: u32 = @as(u32, @intCast(fdes_start)); |
| 448 | 477 | while (i < self.fdes.items.len) { |
| 449 | 478 | const fde = self.fdes.items[i]; |
| 450 | const atom = fde.atom(elf_file); | |
| 479 | const atom_ptr = fde.atom(elf_file); | |
| 451 | 480 | const start = i; |
| 452 | 481 | i += 1; |
| 453 | 482 | while (i < self.fdes.items.len) : (i += 1) { |
| 454 | 483 | const next_fde = self.fdes.items[i]; |
| 455 | if (atom.atom_index != next_fde.atom(elf_file).atom_index) break; | |
| 484 | if (atom_ptr.atom_index != next_fde.atom(elf_file).atom_index) break; | |
| 456 | 485 | } |
| 457 | try atom.addExtra(.{ .fde_start = start, .fde_count = i - start }, elf_file); | |
| 458 | atom.flags.fde = true; | |
| 486 | atom_ptr.addExtra(.{ .fde_start = start, .fde_count = i - start }, elf_file); | |
| 459 | 487 | } |
| 460 | 488 | } |
| 461 | 489 | |
| ... | ... | @@ -498,19 +526,19 @@ fn filterRelocs( |
| 498 | 526 | pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void { |
| 499 | 527 | const comp = elf_file.base.comp; |
| 500 | 528 | const gpa = comp.gpa; |
| 501 | for (self.atoms.items) |atom_index| { | |
| 502 | const atom = elf_file.atom(atom_index) orelse continue; | |
| 503 | if (!atom.flags.alive) continue; | |
| 504 | const shdr = atom.inputShdr(elf_file); | |
| 529 | for (self.atoms_indexes.items) |atom_index| { | |
| 530 | const atom_ptr = self.atom(atom_index) orelse continue; | |
| 531 | if (!atom_ptr.alive) continue; | |
| 532 | const shdr = atom_ptr.inputShdr(elf_file); | |
| 505 | 533 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; |
| 506 | 534 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| 507 | if (atom.scanRelocsRequiresCode(elf_file)) { | |
| 535 | if (atom_ptr.scanRelocsRequiresCode(elf_file)) { | |
| 508 | 536 | // TODO ideally, we don't have to decompress at this stage (should already be done) |
| 509 | 537 | // and we just fetch the code slice. |
| 510 | 538 | const code = try self.codeDecompressAlloc(elf_file, atom_index); |
| 511 | 539 | defer gpa.free(code); |
| 512 | try atom.scanRelocs(elf_file, code, undefs); | |
| 513 | } else try atom.scanRelocs(elf_file, null, undefs); | |
| 540 | try atom_ptr.scanRelocs(elf_file, code, undefs); | |
| 541 | } else try atom_ptr.scanRelocs(elf_file, null, undefs); | |
| 514 | 542 | } |
| 515 | 543 | |
| 516 | 544 | for (self.cies.items) |cie| { |
| ... | ... | @@ -538,19 +566,21 @@ pub fn resolveSymbols(self: *Object, elf_file: *Elf) void { |
| 538 | 566 | if (esym.st_shndx == elf.SHN_UNDEF) continue; |
| 539 | 567 | |
| 540 | 568 | if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) { |
| 541 | const atom_index = self.atoms.items[esym.st_shndx]; | |
| 542 | const atom = elf_file.atom(atom_index) orelse continue; | |
| 543 | if (!atom.flags.alive) continue; | |
| 569 | const atom_index = self.atoms_indexes.items[esym.st_shndx]; | |
| 570 | const atom_ptr = self.atom(atom_index) orelse continue; | |
| 571 | if (!atom_ptr.alive) continue; | |
| 544 | 572 | } |
| 545 | 573 | |
| 546 | 574 | const global = elf_file.symbol(index); |
| 547 | 575 | if (self.asFile().symbolRank(esym, !self.alive) < global.symbolRank(elf_file)) { |
| 548 | const atom_index = switch (esym.st_shndx) { | |
| 549 | elf.SHN_ABS, elf.SHN_COMMON => 0, | |
| 550 | else => self.atoms.items[esym.st_shndx], | |
| 551 | }; | |
| 576 | switch (esym.st_shndx) { | |
| 577 | elf.SHN_ABS, elf.SHN_COMMON => {}, | |
| 578 | else => global.ref = .{ | |
| 579 | .index = self.atoms_indexes.items[esym.st_shndx], | |
| 580 | .file = self.index, | |
| 581 | }, | |
| 582 | } | |
| 552 | 583 | global.value = @intCast(esym.st_value); |
| 553 | global.atom_index = atom_index; | |
| 554 | 584 | global.esym_index = esym_index; |
| 555 | 585 | global.file_index = self.index; |
| 556 | 586 | global.version_index = elf_file.default_sym_version; |
| ... | ... | @@ -579,7 +609,7 @@ pub fn claimUnresolved(self: *Object, elf_file: *Elf) void { |
| 579 | 609 | }; |
| 580 | 610 | |
| 581 | 611 | global.value = 0; |
| 582 | global.atom_index = 0; | |
| 612 | global.ref = .{ .index = 0, .file = 0 }; | |
| 583 | 613 | global.esym_index = esym_index; |
| 584 | 614 | global.file_index = self.index; |
| 585 | 615 | global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version; |
| ... | ... | @@ -600,7 +630,7 @@ pub fn claimUnresolvedObject(self: *Object, elf_file: *Elf) void { |
| 600 | 630 | } |
| 601 | 631 | |
| 602 | 632 | global.value = 0; |
| 603 | global.atom_index = 0; | |
| 633 | global.ref = .{ .index = 0, .file = 0 }; | |
| 604 | 634 | global.esym_index = esym_index; |
| 605 | 635 | global.file_index = self.index; |
| 606 | 636 | } |
| ... | ... | @@ -624,13 +654,13 @@ pub fn markLive(self: *Object, elf_file: *Elf) void { |
| 624 | 654 | } |
| 625 | 655 | } |
| 626 | 656 | |
| 627 | pub fn markEhFrameAtomsDead(self: Object, elf_file: *Elf) void { | |
| 657 | pub fn markEhFrameAtomsDead(self: *Object, elf_file: *Elf) void { | |
| 628 | 658 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 629 | for (self.atoms.items) |atom_index| { | |
| 630 | const atom = elf_file.atom(atom_index) orelse continue; | |
| 631 | const is_eh_frame = (cpu_arch == .x86_64 and atom.inputShdr(elf_file).sh_type == elf.SHT_X86_64_UNWIND) or | |
| 632 | mem.eql(u8, atom.name(elf_file), ".eh_frame"); | |
| 633 | if (atom.flags.alive and is_eh_frame) atom.flags.alive = false; | |
| 659 | for (self.atoms_indexes.items) |atom_index| { | |
| 660 | const atom_ptr = self.atom(atom_index) orelse continue; | |
| 661 | const is_eh_frame = (cpu_arch == .x86_64 and atom_ptr.inputShdr(elf_file).sh_type == elf.SHT_X86_64_UNWIND) or | |
| 662 | mem.eql(u8, atom_ptr.name(elf_file), ".eh_frame"); | |
| 663 | if (atom_ptr.alive and is_eh_frame) atom_ptr.alive = false; | |
| 634 | 664 | } |
| 635 | 665 | } |
| 636 | 666 | |
| ... | ... | @@ -648,9 +678,9 @@ pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutO |
| 648 | 678 | sym.st_shndx == elf.SHN_COMMON) continue; |
| 649 | 679 | |
| 650 | 680 | if (sym.st_shndx != elf.SHN_ABS) { |
| 651 | const atom_index = self.atoms.items[sym.st_shndx]; | |
| 652 | const atom = elf_file.atom(atom_index) orelse continue; | |
| 653 | if (!atom.flags.alive) continue; | |
| 681 | const atom_index = self.atoms_indexes.items[sym.st_shndx]; | |
| 682 | const atom_ptr = self.atom(atom_index) orelse continue; | |
| 683 | if (!atom_ptr.alive) continue; | |
| 654 | 684 | } |
| 655 | 685 | |
| 656 | 686 | const gop = try dupes.getOrPut(index); |
| ... | ... | @@ -661,25 +691,24 @@ pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutO |
| 661 | 691 | } |
| 662 | 692 | } |
| 663 | 693 | |
| 664 | pub fn initMergeSections(self: *Object, elf_file: *Elf) !void { | |
| 694 | pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void { | |
| 665 | 695 | const gpa = elf_file.base.comp.gpa; |
| 666 | 696 | |
| 667 | try self.merge_sections.resize(gpa, self.shdrs.items.len); | |
| 668 | @memset(self.merge_sections.items, 0); | |
| 697 | try self.input_merge_sections.ensureUnusedCapacity(gpa, self.shdrs.items.len); | |
| 698 | try self.input_merge_sections_indexes.resize(gpa, self.shdrs.items.len); | |
| 699 | @memset(self.input_merge_sections_indexes.items, 0); | |
| 669 | 700 | |
| 670 | 701 | for (self.shdrs.items, 0..) |shdr, shndx| { |
| 671 | 702 | if (shdr.sh_flags & elf.SHF_MERGE == 0) continue; |
| 672 | 703 | |
| 673 | const atom_index = self.atoms.items[shndx]; | |
| 674 | const atom_ptr = elf_file.atom(atom_index) orelse continue; | |
| 675 | if (!atom_ptr.flags.alive) continue; | |
| 704 | const atom_index = self.atoms_indexes.items[shndx]; | |
| 705 | const atom_ptr = self.atom(atom_index) orelse continue; | |
| 706 | if (!atom_ptr.alive) continue; | |
| 676 | 707 | if (atom_ptr.relocs(elf_file).len > 0) continue; |
| 677 | 708 | |
| 678 | const imsec_idx = try elf_file.addInputMergeSection(); | |
| 679 | const imsec = elf_file.inputMergeSection(imsec_idx).?; | |
| 680 | self.merge_sections.items[shndx] = imsec_idx; | |
| 681 | ||
| 682 | imsec.merge_section_index = try elf_file.getOrCreateMergeSection(atom_ptr.name(elf_file), shdr.sh_flags, shdr.sh_type); | |
| 709 | const imsec_idx = try self.addInputMergeSection(gpa); | |
| 710 | const imsec = self.inputMergeSection(imsec_idx).?; | |
| 711 | self.input_merge_sections_indexes.items[shndx] = imsec_idx; | |
| 683 | 712 | imsec.atom_index = atom_index; |
| 684 | 713 | |
| 685 | 714 | const data = try self.codeDecompressAlloc(elf_file, atom_index); |
| ... | ... | @@ -734,18 +763,31 @@ pub fn initMergeSections(self: *Object, elf_file: *Elf) !void { |
| 734 | 763 | } |
| 735 | 764 | } |
| 736 | 765 | |
| 737 | atom_ptr.flags.alive = false; | |
| 766 | atom_ptr.alive = false; | |
| 767 | } | |
| 768 | } | |
| 769 | ||
| 770 | pub fn initOutputMergeSections(self: *Object, elf_file: *Elf) !void { | |
| 771 | for (self.input_merge_sections_indexes.items) |index| { | |
| 772 | const imsec = self.inputMergeSection(index) orelse continue; | |
| 773 | const atom_ptr = self.atom(imsec.atom_index).?; | |
| 774 | const shdr = atom_ptr.inputShdr(elf_file); | |
| 775 | imsec.merge_section_index = try elf_file.getOrCreateMergeSection( | |
| 776 | atom_ptr.name(elf_file), | |
| 777 | shdr.sh_flags, | |
| 778 | shdr.sh_type, | |
| 779 | ); | |
| 738 | 780 | } |
| 739 | 781 | } |
| 740 | 782 | |
| 741 | 783 | pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { |
| 742 | 784 | const gpa = elf_file.base.comp.gpa; |
| 743 | 785 | |
| 744 | for (self.merge_sections.items) |index| { | |
| 745 | const imsec = elf_file.inputMergeSection(index) orelse continue; | |
| 786 | for (self.input_merge_sections_indexes.items) |index| { | |
| 787 | const imsec = self.inputMergeSection(index) orelse continue; | |
| 746 | 788 | if (imsec.offsets.items.len == 0) continue; |
| 747 | 789 | const msec = elf_file.mergeSection(imsec.merge_section_index); |
| 748 | const atom_ptr = elf_file.atom(imsec.atom_index).?; | |
| 790 | const atom_ptr = self.atom(imsec.atom_index).?; | |
| 749 | 791 | const isec = atom_ptr.inputShdr(elf_file); |
| 750 | 792 | |
| 751 | 793 | try imsec.subsections.resize(gpa, imsec.strings.items.len); |
| ... | ... | @@ -754,8 +796,8 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { |
| 754 | 796 | const string = imsec.bytes.items[str.pos..][0..str.len]; |
| 755 | 797 | const res = try msec.insert(gpa, string); |
| 756 | 798 | if (!res.found_existing) { |
| 757 | const msub_index = try elf_file.addMergeSubsection(); | |
| 758 | const msub = elf_file.mergeSubsection(msub_index); | |
| 799 | const msub_index = try msec.addMergeSubsection(gpa); | |
| 800 | const msub = msec.mergeSubsection(msub_index); | |
| 759 | 801 | msub.merge_section_index = imsec.merge_section_index; |
| 760 | 802 | msub.string_index = res.key.pos; |
| 761 | 803 | msub.alignment = atom_ptr.alignment; |
| ... | ... | @@ -776,10 +818,10 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { |
| 776 | 818 | |
| 777 | 819 | if (esym.st_shndx == elf.SHN_COMMON or esym.st_shndx == elf.SHN_UNDEF or esym.st_shndx == elf.SHN_ABS) continue; |
| 778 | 820 | |
| 779 | const imsec_index = self.merge_sections.items[esym.st_shndx]; | |
| 780 | const imsec = elf_file.inputMergeSection(imsec_index) orelse continue; | |
| 821 | const imsec_index = self.input_merge_sections_indexes.items[esym.st_shndx]; | |
| 822 | const imsec = self.inputMergeSection(imsec_index) orelse continue; | |
| 781 | 823 | if (imsec.offsets.items.len == 0) continue; |
| 782 | const msub_index, const offset = imsec.findSubsection(@intCast(esym.st_value)) orelse { | |
| 824 | const res = imsec.findSubsection(@intCast(esym.st_value)) orelse { | |
| 783 | 825 | var err = try elf_file.base.addErrorWithNotes(2); |
| 784 | 826 | try err.addMsg("invalid symbol value: {x}", .{esym.st_value}); |
| 785 | 827 | try err.addNote("for symbol {s}", .{sym.name(elf_file)}); |
| ... | ... | @@ -787,45 +829,44 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { |
| 787 | 829 | return error.MalformedObject; |
| 788 | 830 | }; |
| 789 | 831 | |
| 790 | try sym.addExtra(.{ .subsection = msub_index }, elf_file); | |
| 832 | sym.ref = .{ .index = res.msub_index, .file = imsec.merge_section_index }; | |
| 791 | 833 | sym.flags.merge_subsection = true; |
| 792 | sym.value = offset; | |
| 834 | sym.value = res.offset; | |
| 793 | 835 | } |
| 794 | 836 | |
| 795 | for (self.atoms.items) |atom_index| { | |
| 796 | const atom_ptr = elf_file.atom(atom_index) orelse continue; | |
| 797 | if (!atom_ptr.flags.alive) continue; | |
| 798 | const extras = atom_ptr.extra(elf_file) orelse continue; | |
| 837 | for (self.atoms_indexes.items) |atom_index| { | |
| 838 | const atom_ptr = self.atom(atom_index) orelse continue; | |
| 839 | if (!atom_ptr.alive) continue; | |
| 840 | const extras = atom_ptr.extra(elf_file); | |
| 799 | 841 | const relocs = self.relocs.items[extras.rel_index..][0..extras.rel_count]; |
| 800 | 842 | for (relocs) |*rel| { |
| 801 | 843 | const esym = self.symtab.items[rel.r_sym()]; |
| 802 | 844 | if (esym.st_type() != elf.STT_SECTION) continue; |
| 803 | 845 | |
| 804 | const imsec_index = self.merge_sections.items[esym.st_shndx]; | |
| 805 | const imsec = elf_file.inputMergeSection(imsec_index) orelse continue; | |
| 846 | const imsec_index = self.input_merge_sections_indexes.items[esym.st_shndx]; | |
| 847 | const imsec = self.inputMergeSection(imsec_index) orelse continue; | |
| 806 | 848 | if (imsec.offsets.items.len == 0) continue; |
| 807 | const msub_index, const offset = imsec.findSubsection(@intCast(@as(i64, @intCast(esym.st_value)) + rel.r_addend)) orelse { | |
| 849 | const msec = elf_file.mergeSection(imsec.merge_section_index); | |
| 850 | const res = imsec.findSubsection(@intCast(@as(i64, @intCast(esym.st_value)) + rel.r_addend)) orelse { | |
| 808 | 851 | var err = try elf_file.base.addErrorWithNotes(1); |
| 809 | 852 | try err.addMsg("invalid relocation at offset 0x{x}", .{rel.r_offset}); |
| 810 | 853 | try err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); |
| 811 | 854 | return error.MalformedObject; |
| 812 | 855 | }; |
| 813 | const msub = elf_file.mergeSubsection(msub_index); | |
| 814 | const msec = msub.mergeSection(elf_file); | |
| 815 | 856 | |
| 816 | 857 | const out_sym_idx: u64 = @intCast(self.symbols.items.len); |
| 817 | 858 | try self.symbols.ensureUnusedCapacity(gpa, 1); |
| 818 | const name = try std.fmt.allocPrint(gpa, "{s}$subsection{d}", .{ msec.name(elf_file), msub_index }); | |
| 859 | const name = try std.fmt.allocPrint(gpa, "{s}$subsection{d}", .{ msec.name(elf_file), res.msub_index }); | |
| 819 | 860 | defer gpa.free(name); |
| 820 | 861 | const sym_index = try elf_file.addSymbol(); |
| 821 | 862 | const sym = elf_file.symbol(sym_index); |
| 822 | 863 | sym.* = .{ |
| 823 | .value = @bitCast(@as(i64, @intCast(offset)) - rel.r_addend), | |
| 864 | .value = @bitCast(@as(i64, @intCast(res.offset)) - rel.r_addend), | |
| 824 | 865 | .name_offset = try self.addString(gpa, name), |
| 825 | 866 | .esym_index = rel.r_sym(), |
| 826 | 867 | .file_index = self.index, |
| 827 | 868 | }; |
| 828 | try sym.addExtra(.{ .subsection = msub_index }, elf_file); | |
| 869 | sym.ref = .{ .index = res.msub_index, .file = imsec.merge_section_index }; | |
| 829 | 870 | sym.flags.merge_subsection = true; |
| 830 | 871 | self.symbols.addOneAssumeCapacity().* = sym_index; |
| 831 | 872 | rel.r_info = (out_sym_idx << 32) | rel.r_type(); |
| ... | ... | @@ -857,21 +898,10 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void { |
| 857 | 898 | const comp = elf_file.base.comp; |
| 858 | 899 | const gpa = comp.gpa; |
| 859 | 900 | |
| 860 | const atom_index = try elf_file.addAtom(); | |
| 861 | try self.atoms.append(gpa, atom_index); | |
| 862 | ||
| 863 | 901 | const is_tls = global.type(elf_file) == elf.STT_TLS; |
| 864 | 902 | const name = if (is_tls) ".tls_common" else ".common"; |
| 865 | ||
| 866 | const atom = elf_file.atom(atom_index).?; | |
| 867 | 903 | const name_offset = @as(u32, @intCast(self.strtab.items.len)); |
| 868 | 904 | try self.strtab.writer(gpa).print("{s}\x00", .{name}); |
| 869 | atom.atom_index = atom_index; | |
| 870 | atom.name_offset = name_offset; | |
| 871 | atom.file_index = self.index; | |
| 872 | atom.size = this_sym.st_size; | |
| 873 | const alignment = this_sym.st_value; | |
| 874 | atom.alignment = Alignment.fromNonzeroByteUnits(alignment); | |
| 875 | 905 | |
| 876 | 906 | var sh_flags: u32 = elf.SHF_ALLOC | elf.SHF_WRITE; |
| 877 | 907 | if (is_tls) sh_flags |= elf.SHF_TLS; |
| ... | ... | @@ -887,78 +917,84 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void { |
| 887 | 917 | .sh_size = sh_size, |
| 888 | 918 | .sh_link = 0, |
| 889 | 919 | .sh_info = 0, |
| 890 | .sh_addralign = alignment, | |
| 920 | .sh_addralign = this_sym.st_value, | |
| 891 | 921 | .sh_entsize = 0, |
| 892 | 922 | }; |
| 893 | atom.input_section_index = shndx; | |
| 923 | ||
| 924 | const atom_index = try self.addAtom(gpa, .{ | |
| 925 | .name = name_offset, | |
| 926 | .shndx = shndx, | |
| 927 | .size = this_sym.st_size, | |
| 928 | .alignment = Alignment.fromNonzeroByteUnits(this_sym.st_value), | |
| 929 | }); | |
| 930 | try self.atoms_indexes.append(gpa, atom_index); | |
| 894 | 931 | |
| 895 | 932 | global.value = 0; |
| 896 | global.atom_index = atom_index; | |
| 933 | global.ref = .{ .index = atom_index, .file = self.index }; | |
| 897 | 934 | global.flags.weak = false; |
| 898 | 935 | } |
| 899 | 936 | } |
| 900 | 937 | |
| 901 | pub fn initOutputSections(self: Object, elf_file: *Elf) !void { | |
| 902 | for (self.atoms.items) |atom_index| { | |
| 903 | const atom = elf_file.atom(atom_index) orelse continue; | |
| 904 | if (!atom.flags.alive) continue; | |
| 905 | const shdr = atom.inputShdr(elf_file); | |
| 938 | pub fn resolveComdatGroups(self: *Object, elf_file: *Elf, table: anytype) !void { | |
| 939 | for (self.comdat_groups.items, 0..) |*cg, cgi| { | |
| 940 | const signature = cg.signature(elf_file); | |
| 941 | const gop = try table.getOrPut(signature); | |
| 942 | if (!gop.found_existing) { | |
| 943 | gop.value_ptr.* = .{ .index = @intCast(cgi), .file = self.index }; | |
| 944 | continue; | |
| 945 | } | |
| 946 | const current = elf_file.comdatGroup(gop.value_ptr.*); | |
| 947 | cg.alive = false; | |
| 948 | if (self.index < current.file_index) { | |
| 949 | current.alive = false; | |
| 950 | cg.alive = true; | |
| 951 | gop.value_ptr.* = .{ .index = @intCast(cgi), .file = self.index }; | |
| 952 | } | |
| 953 | } | |
| 954 | } | |
| 955 | ||
| 956 | pub fn markComdatGroupsDead(self: *Object, elf_file: *Elf) void { | |
| 957 | for (self.comdat_groups.items) |cg| { | |
| 958 | if (cg.alive) continue; | |
| 959 | for (cg.comdatGroupMembers(elf_file)) |shndx| { | |
| 960 | const atom_index = self.atoms_indexes.items[shndx]; | |
| 961 | if (self.atom(atom_index)) |atom_ptr| { | |
| 962 | atom_ptr.alive = false; | |
| 963 | atom_ptr.markFdesDead(elf_file); | |
| 964 | } | |
| 965 | } | |
| 966 | } | |
| 967 | } | |
| 968 | ||
| 969 | pub fn initOutputSections(self: *Object, elf_file: *Elf) !void { | |
| 970 | for (self.atoms_indexes.items) |atom_index| { | |
| 971 | const atom_ptr = self.atom(atom_index) orelse continue; | |
| 972 | if (!atom_ptr.alive) continue; | |
| 973 | const shdr = atom_ptr.inputShdr(elf_file); | |
| 906 | 974 | _ = try self.initOutputSection(elf_file, shdr); |
| 907 | 975 | } |
| 908 | 976 | } |
| 909 | 977 | |
| 910 | 978 | pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void { |
| 911 | for (self.atoms.items) |atom_index| { | |
| 912 | const atom = elf_file.atom(atom_index) orelse continue; | |
| 913 | if (!atom.flags.alive) continue; | |
| 914 | const shdr = atom.inputShdr(elf_file); | |
| 915 | atom.output_section_index = self.initOutputSection(elf_file, shdr) catch unreachable; | |
| 979 | for (self.atoms_indexes.items) |atom_index| { | |
| 980 | const atom_ptr = self.atom(atom_index) orelse continue; | |
| 981 | if (!atom_ptr.alive) continue; | |
| 982 | const shdr = atom_ptr.inputShdr(elf_file); | |
| 983 | atom_ptr.output_section_index = self.initOutputSection(elf_file, shdr) catch unreachable; | |
| 916 | 984 | |
| 917 | 985 | const comp = elf_file.base.comp; |
| 918 | 986 | const gpa = comp.gpa; |
| 919 | const gop = try elf_file.output_sections.getOrPut(gpa, atom.output_section_index); | |
| 987 | const gop = try elf_file.output_sections.getOrPut(gpa, atom_ptr.output_section_index); | |
| 920 | 988 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 921 | try gop.value_ptr.append(gpa, atom_index); | |
| 922 | } | |
| 923 | ||
| 924 | for (self.locals()) |local_index| { | |
| 925 | const local = elf_file.symbol(local_index); | |
| 926 | if (local.mergeSubsection(elf_file)) |msub| { | |
| 927 | if (!msub.alive) continue; | |
| 928 | local.output_section_index = msub.mergeSection(elf_file).output_section_index; | |
| 929 | continue; | |
| 930 | } | |
| 931 | const atom = local.atom(elf_file) orelse continue; | |
| 932 | if (!atom.flags.alive) continue; | |
| 933 | local.output_section_index = atom.output_section_index; | |
| 934 | } | |
| 935 | ||
| 936 | for (self.globals()) |global_index| { | |
| 937 | const global = elf_file.symbol(global_index); | |
| 938 | if (global.file(elf_file).?.index() != self.index) continue; | |
| 939 | if (global.mergeSubsection(elf_file)) |msub| { | |
| 940 | if (!msub.alive) continue; | |
| 941 | global.output_section_index = msub.mergeSection(elf_file).output_section_index; | |
| 942 | continue; | |
| 943 | } | |
| 944 | const atom = global.atom(elf_file) orelse continue; | |
| 945 | if (!atom.flags.alive) continue; | |
| 946 | global.output_section_index = atom.output_section_index; | |
| 947 | } | |
| 948 | ||
| 949 | for (self.symbols.items[self.symtab.items.len..]) |local_index| { | |
| 950 | const local = elf_file.symbol(local_index); | |
| 951 | const msub = local.mergeSubsection(elf_file).?; | |
| 952 | if (!msub.alive) continue; | |
| 953 | local.output_section_index = msub.mergeSection(elf_file).output_section_index; | |
| 989 | try gop.value_ptr.append(gpa, .{ .index = atom_index, .file = self.index }); | |
| 954 | 990 | } |
| 955 | 991 | } |
| 956 | 992 | |
| 957 | pub fn initRelaSections(self: Object, elf_file: *Elf) !void { | |
| 958 | for (self.atoms.items) |atom_index| { | |
| 959 | const atom = elf_file.atom(atom_index) orelse continue; | |
| 960 | if (!atom.flags.alive) continue; | |
| 961 | const shndx = atom.relocsShndx() orelse continue; | |
| 993 | pub fn initRelaSections(self: *Object, elf_file: *Elf) !void { | |
| 994 | for (self.atoms_indexes.items) |atom_index| { | |
| 995 | const atom_ptr = self.atom(atom_index) orelse continue; | |
| 996 | if (!atom_ptr.alive) continue; | |
| 997 | const shndx = atom_ptr.relocsShndx() orelse continue; | |
| 962 | 998 | const shdr = self.shdrs.items[shndx]; |
| 963 | 999 | const out_shndx = try self.initOutputSection(elf_file, shdr); |
| 964 | 1000 | const out_shdr = &elf_file.shdrs.items[out_shndx]; |
| ... | ... | @@ -968,24 +1004,24 @@ pub fn initRelaSections(self: Object, elf_file: *Elf) !void { |
| 968 | 1004 | } |
| 969 | 1005 | } |
| 970 | 1006 | |
| 971 | pub fn addAtomsToRelaSections(self: Object, elf_file: *Elf) !void { | |
| 972 | for (self.atoms.items) |atom_index| { | |
| 973 | const atom = elf_file.atom(atom_index) orelse continue; | |
| 974 | if (!atom.flags.alive) continue; | |
| 1007 | pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void { | |
| 1008 | for (self.atoms_indexes.items) |atom_index| { | |
| 1009 | const atom_ptr = self.atom(atom_index) orelse continue; | |
| 1010 | if (!atom_ptr.alive) continue; | |
| 975 | 1011 | const shndx = blk: { |
| 976 | const shndx = atom.relocsShndx() orelse continue; | |
| 1012 | const shndx = atom_ptr.relocsShndx() orelse continue; | |
| 977 | 1013 | const shdr = self.shdrs.items[shndx]; |
| 978 | 1014 | break :blk self.initOutputSection(elf_file, shdr) catch unreachable; |
| 979 | 1015 | }; |
| 980 | 1016 | const shdr = &elf_file.shdrs.items[shndx]; |
| 981 | shdr.sh_info = atom.outputShndx().?; | |
| 1017 | shdr.sh_info = atom_ptr.output_section_index; | |
| 982 | 1018 | shdr.sh_link = elf_file.symtab_section_index.?; |
| 983 | 1019 | |
| 984 | 1020 | const comp = elf_file.base.comp; |
| 985 | 1021 | const gpa = comp.gpa; |
| 986 | const gop = try elf_file.output_rela_sections.getOrPut(gpa, atom.outputShndx().?); | |
| 1022 | const gop = try elf_file.output_rela_sections.getOrPut(gpa, atom_ptr.output_section_index); | |
| 987 | 1023 | if (!gop.found_existing) gop.value_ptr.* = .{ .shndx = shndx }; |
| 988 | try gop.value_ptr.atom_list.append(gpa, atom_index); | |
| 1024 | try gop.value_ptr.atom_list.append(gpa, .{ .index = atom_index, .file = self.index }); | |
| 989 | 1025 | } |
| 990 | 1026 | } |
| 991 | 1027 | |
| ... | ... | @@ -1041,7 +1077,7 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void { |
| 1041 | 1077 | const isAlive = struct { |
| 1042 | 1078 | fn isAlive(sym: *const Symbol, ctx: *Elf) bool { |
| 1043 | 1079 | if (sym.mergeSubsection(ctx)) |msub| return msub.alive; |
| 1044 | if (sym.atom(ctx)) |atom_ptr| return atom_ptr.flags.alive; | |
| 1080 | if (sym.atom(ctx)) |atom_ptr| return atom_ptr.alive; | |
| 1045 | 1081 | return true; |
| 1046 | 1082 | } |
| 1047 | 1083 | }.isAlive; |
| ... | ... | @@ -1119,11 +1155,10 @@ pub fn globals(self: Object) []const Symbol.Index { |
| 1119 | 1155 | |
| 1120 | 1156 | /// Returns atom's code and optionally uncompresses data if required (for compressed sections). |
| 1121 | 1157 | /// Caller owns the memory. |
| 1122 | pub fn codeDecompressAlloc(self: Object, elf_file: *Elf, atom_index: Atom.Index) ![]u8 { | |
| 1158 | pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index) ![]u8 { | |
| 1123 | 1159 | const comp = elf_file.base.comp; |
| 1124 | 1160 | const gpa = comp.gpa; |
| 1125 | const atom_ptr = elf_file.atom(atom_index).?; | |
| 1126 | assert(atom_ptr.file_index == self.index); | |
| 1161 | const atom_ptr = self.atom(atom_index).?; | |
| 1127 | 1162 | const shdr = atom_ptr.inputShdr(elf_file); |
| 1128 | 1163 | const handle = elf_file.fileHandle(self.file_handle); |
| 1129 | 1164 | const data = try self.preadShdrContentsAlloc(gpa, handle, atom_ptr.input_section_index); |
| ... | ... | @@ -1184,6 +1219,105 @@ fn preadRelocsAlloc(self: Object, allocator: Allocator, handle: std.fs.File, shn |
| 1184 | 1219 | return @as([*]align(1) const elf.Elf64_Rela, @ptrCast(raw.ptr))[0..num]; |
| 1185 | 1220 | } |
| 1186 | 1221 | |
| 1222 | const AddAtomArgs = struct { | |
| 1223 | name: u32, | |
| 1224 | shndx: u32, | |
| 1225 | size: u64, | |
| 1226 | alignment: Alignment, | |
| 1227 | }; | |
| 1228 | ||
| 1229 | fn addAtom(self: *Object, allocator: Allocator, args: AddAtomArgs) !Atom.Index { | |
| 1230 | try self.atoms.ensureUnusedCapacity(allocator, 1); | |
| 1231 | try self.atoms_extra.ensureUnusedCapacity(allocator, @sizeOf(Atom.Extra)); | |
| 1232 | return self.addAtomAssumeCapacity(args); | |
| 1233 | } | |
| 1234 | ||
| 1235 | fn addAtomAssumeCapacity(self: *Object, args: AddAtomArgs) Atom.Index { | |
| 1236 | const atom_index: Atom.Index = @intCast(self.atoms.items.len); | |
| 1237 | const atom_ptr = self.atoms.addOneAssumeCapacity(); | |
| 1238 | atom_ptr.* = .{ | |
| 1239 | .atom_index = atom_index, | |
| 1240 | .name_offset = args.name, | |
| 1241 | .file_index = self.index, | |
| 1242 | .input_section_index = args.shndx, | |
| 1243 | .extra_index = self.addAtomExtraAssumeCapacity(.{}), | |
| 1244 | .size = args.size, | |
| 1245 | .alignment = args.alignment, | |
| 1246 | }; | |
| 1247 | return atom_index; | |
| 1248 | } | |
| 1249 | ||
| 1250 | pub fn atom(self: *Object, atom_index: Atom.Index) ?*Atom { | |
| 1251 | if (atom_index == 0) return null; | |
| 1252 | assert(atom_index < self.atoms.items.len); | |
| 1253 | return &self.atoms.items[atom_index]; | |
| 1254 | } | |
| 1255 | ||
| 1256 | pub fn addAtomExtra(self: *Object, allocator: Allocator, extra: Atom.Extra) !u32 { | |
| 1257 | const fields = @typeInfo(Atom.Extra).Struct.fields; | |
| 1258 | try self.atoms_extra.ensureUnusedCapacity(allocator, fields.len); | |
| 1259 | return self.addAtomExtraAssumeCapacity(extra); | |
| 1260 | } | |
| 1261 | ||
| 1262 | pub fn addAtomExtraAssumeCapacity(self: *Object, extra: Atom.Extra) u32 { | |
| 1263 | const index = @as(u32, @intCast(self.atoms_extra.items.len)); | |
| 1264 | const fields = @typeInfo(Atom.Extra).Struct.fields; | |
| 1265 | inline for (fields) |field| { | |
| 1266 | self.atoms_extra.appendAssumeCapacity(switch (field.type) { | |
| 1267 | u32 => @field(extra, field.name), | |
| 1268 | else => @compileError("bad field type"), | |
| 1269 | }); | |
| 1270 | } | |
| 1271 | return index; | |
| 1272 | } | |
| 1273 | ||
| 1274 | pub fn atomExtra(self: *Object, index: u32) Atom.Extra { | |
| 1275 | const fields = @typeInfo(Atom.Extra).Struct.fields; | |
| 1276 | var i: usize = index; | |
| 1277 | var result: Atom.Extra = undefined; | |
| 1278 | inline for (fields) |field| { | |
| 1279 | @field(result, field.name) = switch (field.type) { | |
| 1280 | u32 => self.atoms_extra.items[i], | |
| 1281 | else => @compileError("bad field type"), | |
| 1282 | }; | |
| 1283 | i += 1; | |
| 1284 | } | |
| 1285 | return result; | |
| 1286 | } | |
| 1287 | ||
| 1288 | pub fn setAtomExtra(self: *Object, index: u32, extra: Atom.Extra) void { | |
| 1289 | const fields = @typeInfo(Atom.Extra).Struct.fields; | |
| 1290 | inline for (fields, 0..) |field, i| { | |
| 1291 | self.atoms_extra.items[index + i] = switch (field.type) { | |
| 1292 | u32 => @field(extra, field.name), | |
| 1293 | else => @compileError("bad field type"), | |
| 1294 | }; | |
| 1295 | } | |
| 1296 | } | |
| 1297 | ||
| 1298 | fn addInputMergeSection(self: *Object, allocator: Allocator) !InputMergeSection.Index { | |
| 1299 | const index: InputMergeSection.Index = @intCast(self.input_merge_sections.items.len); | |
| 1300 | const msec = try self.input_merge_sections.addOne(allocator); | |
| 1301 | msec.* = .{}; | |
| 1302 | return index; | |
| 1303 | } | |
| 1304 | ||
| 1305 | fn inputMergeSection(self: *Object, index: InputMergeSection.Index) ?*InputMergeSection { | |
| 1306 | if (index == 0) return null; | |
| 1307 | return &self.input_merge_sections.items[index]; | |
| 1308 | } | |
| 1309 | ||
| 1310 | fn addComdatGroup(self: *Object, allocator: Allocator) !Elf.ComdatGroup.Index { | |
| 1311 | const index = @as(Elf.ComdatGroup.Index, @intCast(self.comdat_groups.items.len)); | |
| 1312 | _ = try self.comdat_groups.addOne(allocator); | |
| 1313 | return index; | |
| 1314 | } | |
| 1315 | ||
| 1316 | pub fn comdatGroup(self: *Object, index: Elf.ComdatGroup.Index) *Elf.ComdatGroup { | |
| 1317 | assert(index < self.comdat_groups.items.len); | |
| 1318 | return &self.comdat_groups.items[index]; | |
| 1319 | } | |
| 1320 | ||
| 1187 | 1321 | pub fn format( |
| 1188 | 1322 | self: *Object, |
| 1189 | 1323 | comptime unused_fmt_string: []const u8, |
| ... | ... | @@ -1247,9 +1381,9 @@ fn formatAtoms( |
| 1247 | 1381 | _ = options; |
| 1248 | 1382 | const object = ctx.object; |
| 1249 | 1383 | try writer.writeAll(" atoms\n"); |
| 1250 | for (object.atoms.items) |atom_index| { | |
| 1251 | const atom = ctx.elf_file.atom(atom_index) orelse continue; | |
| 1252 | try writer.print(" {}\n", .{atom.fmt(ctx.elf_file)}); | |
| 1384 | for (object.atoms_indexes.items) |atom_index| { | |
| 1385 | const atom_ptr = object.atom(atom_index) orelse continue; | |
| 1386 | try writer.print(" {}\n", .{atom_ptr.fmt(ctx.elf_file)}); | |
| 1253 | 1387 | } |
| 1254 | 1388 | } |
| 1255 | 1389 | |
| ... | ... | @@ -1315,16 +1449,15 @@ fn formatComdatGroups( |
| 1315 | 1449 | const object = ctx.object; |
| 1316 | 1450 | const elf_file = ctx.elf_file; |
| 1317 | 1451 | try writer.writeAll(" COMDAT groups\n"); |
| 1318 | for (object.comdat_groups.items) |cg_index| { | |
| 1319 | const cg = elf_file.comdatGroup(cg_index); | |
| 1320 | const cg_owner = elf_file.comdatGroupOwner(cg.owner); | |
| 1321 | if (cg_owner.file != object.index) continue; | |
| 1322 | try writer.print(" COMDAT({d})\n", .{cg_index}); | |
| 1452 | for (object.comdat_groups.items, 0..) |cg, cg_index| { | |
| 1453 | try writer.print(" COMDAT({d})", .{cg_index}); | |
| 1454 | if (!cg.alive) try writer.writeAll(" : [*]"); | |
| 1455 | try writer.writeByte('\n'); | |
| 1323 | 1456 | const cg_members = cg.comdatGroupMembers(elf_file); |
| 1324 | 1457 | for (cg_members) |shndx| { |
| 1325 | const atom_index = object.atoms.items[shndx]; | |
| 1326 | const atom = elf_file.atom(atom_index) orelse continue; | |
| 1327 | try writer.print(" atom({d}) : {s}\n", .{ atom_index, atom.name(elf_file) }); | |
| 1458 | const atom_index = object.atoms_indexes.items[shndx]; | |
| 1459 | const atom_ptr = object.atom(atom_index) orelse continue; | |
| 1460 | try writer.print(" atom({d}) : {s}\n", .{ atom_index, atom_ptr.name(elf_file) }); | |
| 1328 | 1461 | } |
| 1329 | 1462 | } |
| 1330 | 1463 | } |
src/link/Elf/SharedObject.zig+1-1| ... | ... | @@ -232,7 +232,7 @@ pub fn resolveSymbols(self: *SharedObject, elf_file: *Elf) void { |
| 232 | 232 | const global = elf_file.symbol(index); |
| 233 | 233 | if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) { |
| 234 | 234 | global.value = @intCast(this_sym.st_value); |
| 235 | global.atom_index = 0; | |
| 235 | global.ref = .{ .index = 0, .file = 0 }; | |
| 236 | 236 | global.esym_index = esym_index; |
| 237 | 237 | global.version_index = self.versyms.items[esym_index]; |
| 238 | 238 | global.file_index = self.index; |
src/link/Elf/Symbol.zig+25-20| ... | ... | @@ -9,10 +9,9 @@ name_offset: u32 = 0, |
| 9 | 9 | /// Index of file where this symbol is defined. |
| 10 | 10 | file_index: File.Index = 0, |
| 11 | 11 | |
| 12 | /// Index of atom containing this symbol. | |
| 13 | /// Index of 0 means there is no associated atom with this symbol. | |
| 14 | /// Use `atom` to get the pointer to the atom. | |
| 15 | atom_index: Atom.Index = 0, | |
| 12 | /// Reference to Atom or merge subsection containing this symbol if any. | |
| 13 | /// Use `atom` or `mergeSubsection` to get the pointer to the atom. | |
| 14 | ref: Elf.Ref = .{ .index = 0, .file = 0 }, | |
| 16 | 15 | |
| 17 | 16 | /// Assigned output section index for this symbol. |
| 18 | 17 | output_section_index: u32 = 0, |
| ... | ... | @@ -34,11 +33,15 @@ pub fn isAbs(symbol: Symbol, elf_file: *Elf) bool { |
| 34 | 33 | const file_ptr = symbol.file(elf_file).?; |
| 35 | 34 | if (file_ptr == .shared_object) return symbol.elfSym(elf_file).st_shndx == elf.SHN_ABS; |
| 36 | 35 | return !symbol.flags.import and symbol.atom(elf_file) == null and |
| 37 | symbol.mergeSubsection(elf_file) == null and symbol.outputShndx() == null and | |
| 36 | symbol.mergeSubsection(elf_file) == null and symbol.outputShndx(elf_file) == null and | |
| 38 | 37 | file_ptr != .linker_defined; |
| 39 | 38 | } |
| 40 | 39 | |
| 41 | pub fn outputShndx(symbol: Symbol) ?u32 { | |
| 40 | pub fn outputShndx(symbol: Symbol, elf_file: *Elf) ?u32 { | |
| 41 | if (symbol.mergeSubsection(elf_file)) |msub| | |
| 42 | return if (msub.alive) msub.mergeSection(elf_file).output_section_index else null; | |
| 43 | if (symbol.atom(elf_file)) |atom_ptr| | |
| 44 | return if (atom_ptr.alive) atom_ptr.output_section_index else null; | |
| 42 | 45 | if (symbol.output_section_index == 0) return null; |
| 43 | 46 | return symbol.output_section_index; |
| 44 | 47 | } |
| ... | ... | @@ -68,13 +71,15 @@ pub fn name(symbol: Symbol, elf_file: *Elf) [:0]const u8 { |
| 68 | 71 | } |
| 69 | 72 | |
| 70 | 73 | pub fn atom(symbol: Symbol, elf_file: *Elf) ?*Atom { |
| 71 | return elf_file.atom(symbol.atom_index); | |
| 74 | if (symbol.flags.merge_subsection) return null; | |
| 75 | const file_ptr = elf_file.file(symbol.ref.file) orelse return null; | |
| 76 | return file_ptr.atom(symbol.ref.index); | |
| 72 | 77 | } |
| 73 | 78 | |
| 74 | 79 | pub fn mergeSubsection(symbol: Symbol, elf_file: *Elf) ?*MergeSubsection { |
| 75 | 80 | if (!symbol.flags.merge_subsection) return null; |
| 76 | const extras = symbol.extra(elf_file).?; | |
| 77 | return elf_file.mergeSubsection(extras.subsection); | |
| 81 | const msec = elf_file.mergeSection(symbol.ref.file); | |
| 82 | return msec.mergeSubsection(symbol.ref.index); | |
| 78 | 83 | } |
| 79 | 84 | |
| 80 | 85 | pub fn file(symbol: Symbol, elf_file: *Elf) ?File { |
| ... | ... | @@ -116,7 +121,7 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true }, elf_file: *Elf |
| 116 | 121 | return symbol.pltAddress(elf_file); |
| 117 | 122 | } |
| 118 | 123 | if (symbol.atom(elf_file)) |atom_ptr| { |
| 119 | if (!atom_ptr.flags.alive) { | |
| 124 | if (!atom_ptr.alive) { | |
| 120 | 125 | if (mem.eql(u8, atom_ptr.name(elf_file), ".eh_frame")) { |
| 121 | 126 | const sym_name = symbol.name(elf_file); |
| 122 | 127 | const sh_addr, const sh_size = blk: { |
| ... | ... | @@ -258,7 +263,6 @@ const AddExtraOpts = struct { |
| 258 | 263 | gottp: ?u32 = null, |
| 259 | 264 | tlsdesc: ?u32 = null, |
| 260 | 265 | zig_got: ?u32 = null, |
| 261 | subsection: ?u32 = null, | |
| 262 | 266 | }; |
| 263 | 267 | |
| 264 | 268 | pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) !void { |
| ... | ... | @@ -298,7 +302,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void { |
| 298 | 302 | if (elf_file.base.isRelocatable() and esym.st_shndx == elf.SHN_COMMON) break :blk elf.SHN_COMMON; |
| 299 | 303 | if (symbol.mergeSubsection(elf_file)) |msub| break :blk @intCast(msub.mergeSection(elf_file).output_section_index); |
| 300 | 304 | if (symbol.atom(elf_file) == null and file_ptr != .linker_defined) break :blk elf.SHN_ABS; |
| 301 | break :blk @intCast(symbol.outputShndx() orelse elf.SHN_UNDEF); | |
| 305 | break :blk @intCast(symbol.outputShndx(elf_file) orelse elf.SHN_UNDEF); | |
| 302 | 306 | }; |
| 303 | 307 | const st_value = blk: { |
| 304 | 308 | if (symbol.flags.has_copy_rel) break :blk symbol.address(.{}, elf_file); |
| ... | ... | @@ -382,22 +386,23 @@ fn format2( |
| 382 | 386 | _ = options; |
| 383 | 387 | _ = unused_fmt_string; |
| 384 | 388 | const symbol = ctx.symbol; |
| 389 | const elf_file = ctx.elf_file; | |
| 385 | 390 | try writer.print("%{d} : {s} : @{x}", .{ |
| 386 | 391 | symbol.esym_index, |
| 387 | symbol.fmtName(ctx.elf_file), | |
| 388 | symbol.address(.{}, ctx.elf_file), | |
| 392 | symbol.fmtName(elf_file), | |
| 393 | symbol.address(.{}, elf_file), | |
| 389 | 394 | }); |
| 390 | if (symbol.file(ctx.elf_file)) |file_ptr| { | |
| 391 | if (symbol.isAbs(ctx.elf_file)) { | |
| 392 | if (symbol.elfSym(ctx.elf_file).st_shndx == elf.SHN_UNDEF) { | |
| 395 | if (symbol.file(elf_file)) |file_ptr| { | |
| 396 | if (symbol.isAbs(elf_file)) { | |
| 397 | if (symbol.elfSym(elf_file).st_shndx == elf.SHN_UNDEF) { | |
| 393 | 398 | try writer.writeAll(" : undef"); |
| 394 | 399 | } else { |
| 395 | 400 | try writer.writeAll(" : absolute"); |
| 396 | 401 | } |
| 397 | } else if (symbol.outputShndx()) |shndx| { | |
| 402 | } else if (symbol.outputShndx(elf_file)) |shndx| { | |
| 398 | 403 | try writer.print(" : shdr({d})", .{shndx}); |
| 399 | 404 | } |
| 400 | if (symbol.atom(ctx.elf_file)) |atom_ptr| { | |
| 405 | if (symbol.atom(elf_file)) |atom_ptr| { | |
| 401 | 406 | try writer.print(" : atom({d})", .{atom_ptr.atom_index}); |
| 402 | 407 | } |
| 403 | 408 | var buf: [2]u8 = .{'_'} ** 2; |
| ... | ... | @@ -483,7 +488,7 @@ pub const Extra = struct { |
| 483 | 488 | gottp: u32 = 0, |
| 484 | 489 | tlsdesc: u32 = 0, |
| 485 | 490 | zig_got: u32 = 0, |
| 486 | subsection: u32 = 0, | |
| 491 | merge_section: u32 = 0, | |
| 487 | 492 | }; |
| 488 | 493 | |
| 489 | 494 | pub const Index = u32; |
src/link/Elf/ZigObject.zig+138-82| ... | ... | @@ -15,7 +15,9 @@ local_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 15 | 15 | global_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 16 | 16 | globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{}, |
| 17 | 17 | |
| 18 | atoms: std.ArrayListUnmanaged(Atom.Index) = .{}, | |
| 18 | atoms: std.ArrayListUnmanaged(Atom) = .{}, | |
| 19 | atoms_indexes: std.ArrayListUnmanaged(Atom.Index) = .{}, | |
| 20 | atoms_extra: std.ArrayListUnmanaged(u32) = .{}, | |
| 19 | 21 | relocs: std.ArrayListUnmanaged(std.ArrayListUnmanaged(elf.Elf64_Rela)) = .{}, |
| 20 | 22 | |
| 21 | 23 | num_dynrelocs: u32 = 0, |
| ... | ... | @@ -80,7 +82,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void { |
| 80 | 82 | const comp = elf_file.base.comp; |
| 81 | 83 | const gpa = comp.gpa; |
| 82 | 84 | |
| 83 | try self.atoms.append(gpa, 0); // null input section | |
| 85 | try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) }); // null input section | |
| 84 | 86 | try self.relocs.append(gpa, .{}); // null relocs section |
| 85 | 87 | try self.strtab.buffer.append(gpa, 0); |
| 86 | 88 | |
| ... | ... | @@ -117,6 +119,8 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void { |
| 117 | 119 | self.global_symbols.deinit(allocator); |
| 118 | 120 | self.globals_lookup.deinit(allocator); |
| 119 | 121 | self.atoms.deinit(allocator); |
| 122 | self.atoms_indexes.deinit(allocator); | |
| 123 | self.atoms_extra.deinit(allocator); | |
| 120 | 124 | for (self.relocs.items) |*list| { |
| 121 | 125 | list.deinit(allocator); |
| 122 | 126 | } |
| ... | ... | @@ -276,24 +280,20 @@ pub fn addGlobalEsym(self: *ZigObject, allocator: Allocator) !Symbol.Index { |
| 276 | 280 | return index | global_symbol_bit; |
| 277 | 281 | } |
| 278 | 282 | |
| 279 | pub fn addAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index { | |
| 283 | pub fn newAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index { | |
| 280 | 284 | const gpa = elf_file.base.comp.gpa; |
| 281 | const atom_index = try elf_file.addAtom(); | |
| 285 | const atom_index = try self.addAtom(gpa); | |
| 282 | 286 | const symbol_index = try elf_file.addSymbol(); |
| 283 | 287 | const esym_index = try self.addLocalEsym(gpa); |
| 284 | 288 | |
| 285 | const shndx = @as(u32, @intCast(self.atoms.items.len)); | |
| 286 | try self.atoms.append(gpa, atom_index); | |
| 289 | try self.atoms_indexes.append(gpa, atom_index); | |
| 287 | 290 | try self.local_symbols.append(gpa, symbol_index); |
| 288 | 291 | |
| 289 | const atom_ptr = elf_file.atom(atom_index).?; | |
| 290 | atom_ptr.file_index = self.index; | |
| 291 | ||
| 292 | 292 | const symbol_ptr = elf_file.symbol(symbol_index); |
| 293 | 293 | symbol_ptr.file_index = self.index; |
| 294 | symbol_ptr.atom_index = atom_index; | |
| 294 | symbol_ptr.ref = .{ .index = atom_index, .file = self.index }; | |
| 295 | 295 | |
| 296 | self.local_esyms.items(.shndx)[esym_index] = shndx; | |
| 296 | self.local_esyms.items(.shndx)[esym_index] = atom_index; | |
| 297 | 297 | self.local_esyms.items(.elf_sym)[esym_index].st_shndx = SHN_ATOM; |
| 298 | 298 | symbol_ptr.esym_index = esym_index; |
| 299 | 299 | |
| ... | ... | @@ -301,21 +301,22 @@ pub fn addAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index { |
| 301 | 301 | const relocs_index = @as(u32, @intCast(self.relocs.items.len)); |
| 302 | 302 | const relocs = try self.relocs.addOne(gpa); |
| 303 | 303 | relocs.* = .{}; |
| 304 | ||
| 305 | const atom_ptr = self.atom(atom_index).?; | |
| 304 | 306 | atom_ptr.relocs_section_index = relocs_index; |
| 305 | 307 | |
| 306 | 308 | return symbol_index; |
| 307 | 309 | } |
| 308 | 310 | |
| 309 | 311 | /// TODO actually create fake input shdrs and return that instead. |
| 310 | pub fn inputShdr(self: ZigObject, atom_index: Atom.Index, elf_file: *Elf) elf.Elf64_Shdr { | |
| 311 | _ = self; | |
| 312 | const atom = elf_file.atom(atom_index) orelse return Elf.null_shdr; | |
| 313 | const shndx = atom.outputShndx() orelse return Elf.null_shdr; | |
| 312 | pub fn inputShdr(self: *ZigObject, atom_index: Atom.Index, elf_file: *Elf) elf.Elf64_Shdr { | |
| 313 | const atom_ptr = self.atom(atom_index) orelse return Elf.null_shdr; | |
| 314 | const shndx = atom_ptr.output_section_index; | |
| 314 | 315 | var shdr = elf_file.shdrs.items[shndx]; |
| 315 | 316 | shdr.sh_addr = 0; |
| 316 | 317 | shdr.sh_offset = 0; |
| 317 | shdr.sh_size = atom.size; | |
| 318 | shdr.sh_addralign = atom.alignment.toByteUnits() orelse 1; | |
| 318 | shdr.sh_size = atom_ptr.size; | |
| 319 | shdr.sh_addralign = atom_ptr.alignment.toByteUnits() orelse 1; | |
| 319 | 320 | return shdr; |
| 320 | 321 | } |
| 321 | 322 | |
| ... | ... | @@ -329,27 +330,21 @@ pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) void { |
| 329 | 330 | |
| 330 | 331 | if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) { |
| 331 | 332 | assert(esym.st_shndx == SHN_ATOM); |
| 332 | const atom_index = self.atoms.items[shndx]; | |
| 333 | const atom = elf_file.atom(atom_index) orelse continue; | |
| 334 | if (!atom.flags.alive) continue; | |
| 333 | const atom_ptr = self.atom(shndx) orelse continue; | |
| 334 | if (!atom_ptr.alive) continue; | |
| 335 | 335 | } |
| 336 | 336 | |
| 337 | 337 | const global = elf_file.symbol(index); |
| 338 | 338 | if (self.asFile().symbolRank(esym, false) < global.symbolRank(elf_file)) { |
| 339 | 339 | const atom_index = switch (esym.st_shndx) { |
| 340 | 340 | elf.SHN_ABS, elf.SHN_COMMON => 0, |
| 341 | SHN_ATOM => self.atoms.items[shndx], | |
| 341 | SHN_ATOM => shndx, | |
| 342 | 342 | else => unreachable, |
| 343 | 343 | }; |
| 344 | const output_section_index = if (elf_file.atom(atom_index)) |atom| | |
| 345 | atom.outputShndx().? | |
| 346 | else | |
| 347 | elf.SHN_UNDEF; | |
| 348 | 344 | global.value = @intCast(esym.st_value); |
| 349 | global.atom_index = atom_index; | |
| 345 | global.ref = .{ .index = atom_index, .file = self.index }; | |
| 350 | 346 | global.esym_index = esym_index; |
| 351 | 347 | global.file_index = self.index; |
| 352 | global.output_section_index = output_section_index; | |
| 353 | 348 | global.version_index = elf_file.default_sym_version; |
| 354 | 349 | if (esym.st_bind() == elf.STB_WEAK) global.flags.weak = true; |
| 355 | 350 | } |
| ... | ... | @@ -376,7 +371,7 @@ pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void { |
| 376 | 371 | }; |
| 377 | 372 | |
| 378 | 373 | global.value = 0; |
| 379 | global.atom_index = 0; | |
| 374 | global.ref = .{ .index = 0, .file = 0 }; | |
| 380 | 375 | global.esym_index = esym_index; |
| 381 | 376 | global.file_index = self.index; |
| 382 | 377 | global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version; |
| ... | ... | @@ -397,7 +392,7 @@ pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void { |
| 397 | 392 | } |
| 398 | 393 | |
| 399 | 394 | global.value = 0; |
| 400 | global.atom_index = 0; | |
| 395 | global.ref = .{ .index = 0, .file = 0 }; | |
| 401 | 396 | global.esym_index = esym_index; |
| 402 | 397 | global.file_index = self.index; |
| 403 | 398 | } |
| ... | ... | @@ -405,19 +400,19 @@ pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void { |
| 405 | 400 | |
| 406 | 401 | pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void { |
| 407 | 402 | const gpa = elf_file.base.comp.gpa; |
| 408 | for (self.atoms.items) |atom_index| { | |
| 409 | const atom = elf_file.atom(atom_index) orelse continue; | |
| 410 | if (!atom.flags.alive) continue; | |
| 411 | const shdr = atom.inputShdr(elf_file); | |
| 403 | for (self.atoms_indexes.items) |atom_index| { | |
| 404 | const atom_ptr = self.atom(atom_index) orelse continue; | |
| 405 | if (!atom_ptr.alive) continue; | |
| 406 | const shdr = atom_ptr.inputShdr(elf_file); | |
| 412 | 407 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| 413 | if (atom.scanRelocsRequiresCode(elf_file)) { | |
| 408 | if (atom_ptr.scanRelocsRequiresCode(elf_file)) { | |
| 414 | 409 | // TODO ideally we don't have to fetch the code here. |
| 415 | 410 | // Perhaps it would make sense to save the code until flushModule where we |
| 416 | 411 | // would free all of generated code? |
| 417 | 412 | const code = try self.codeAlloc(elf_file, atom_index); |
| 418 | 413 | defer gpa.free(code); |
| 419 | try atom.scanRelocs(elf_file, code, undefs); | |
| 420 | } else try atom.scanRelocs(elf_file, null, undefs); | |
| 414 | try atom_ptr.scanRelocs(elf_file, code, undefs); | |
| 415 | } else try atom_ptr.scanRelocs(elf_file, null, undefs); | |
| 421 | 416 | } |
| 422 | 417 | } |
| 423 | 418 | |
| ... | ... | @@ -450,9 +445,8 @@ pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{O |
| 450 | 445 | esym.st_shndx == elf.SHN_COMMON) continue; |
| 451 | 446 | |
| 452 | 447 | if (esym.st_shndx == SHN_ATOM) { |
| 453 | const atom_index = self.atoms.items[shndx]; | |
| 454 | const atom = elf_file.atom(atom_index) orelse continue; | |
| 455 | if (!atom.flags.alive) continue; | |
| 448 | const atom_ptr = self.atom(shndx) orelse continue; | |
| 449 | if (!atom_ptr.alive) continue; | |
| 456 | 450 | } |
| 457 | 451 | |
| 458 | 452 | const gop = try dupes.getOrPut(index); |
| ... | ... | @@ -493,7 +487,7 @@ pub fn updateArSymtab(self: ZigObject, ar_symtab: *Archive.ArSymtab, elf_file: * |
| 493 | 487 | const global = elf_file.symbol(global_index); |
| 494 | 488 | const file_ptr = global.file(elf_file).?; |
| 495 | 489 | assert(file_ptr.index() == self.index); |
| 496 | if (global.outputShndx() == null) continue; | |
| 490 | if (global.outputShndx(elf_file) == null) continue; | |
| 497 | 491 | |
| 498 | 492 | const off = try ar_symtab.strtab.insert(gpa, global.name(elf_file)); |
| 499 | 493 | ar_symtab.symtab.appendAssumeCapacity(.{ .off = off, .file_index = self.index }); |
| ... | ... | @@ -517,20 +511,20 @@ pub fn writeAr(self: ZigObject, writer: anytype) !void { |
| 517 | 511 | try writer.writeAll(self.data.items); |
| 518 | 512 | } |
| 519 | 513 | |
| 520 | pub fn addAtomsToRelaSections(self: ZigObject, elf_file: *Elf) !void { | |
| 521 | for (self.atoms.items) |atom_index| { | |
| 522 | const atom = elf_file.atom(atom_index) orelse continue; | |
| 523 | if (!atom.flags.alive) continue; | |
| 524 | const rela_shndx = atom.relocsShndx() orelse continue; | |
| 514 | pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void { | |
| 515 | for (self.atoms_indexes.items) |atom_index| { | |
| 516 | const atom_ptr = self.atom(atom_index) orelse continue; | |
| 517 | if (!atom_ptr.alive) continue; | |
| 518 | const rela_shndx = atom_ptr.relocsShndx() orelse continue; | |
| 525 | 519 | // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level |
| 526 | 520 | if (self.relocs.items[rela_shndx].items.len == 0) continue; |
| 527 | const out_shndx = atom.outputShndx().?; | |
| 521 | const out_shndx = atom_ptr.output_section_index; | |
| 528 | 522 | const out_shdr = elf_file.shdrs.items[out_shndx]; |
| 529 | 523 | if (out_shdr.sh_type == elf.SHT_NOBITS) continue; |
| 530 | 524 | |
| 531 | 525 | const gpa = elf_file.base.comp.gpa; |
| 532 | 526 | const sec = elf_file.output_rela_sections.getPtr(out_shndx).?; |
| 533 | try sec.atom_list.append(gpa, atom_index); | |
| 527 | try sec.atom_list.append(gpa, .{ .index = atom_index, .file = self.index }); | |
| 534 | 528 | } |
| 535 | 529 | } |
| 536 | 530 | |
| ... | ... | @@ -561,7 +555,7 @@ pub fn globals(self: ZigObject) []const Symbol.Index { |
| 561 | 555 | pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void { |
| 562 | 556 | for (self.locals()) |local_index| { |
| 563 | 557 | const local = elf_file.symbol(local_index); |
| 564 | if (local.atom(elf_file)) |atom| if (!atom.flags.alive) continue; | |
| 558 | if (local.atom(elf_file)) |atom_ptr| if (!atom_ptr.alive) continue; | |
| 565 | 559 | const esym = local.elfSym(elf_file); |
| 566 | 560 | switch (esym.st_type()) { |
| 567 | 561 | elf.STT_SECTION, elf.STT_NOTYPE => continue, |
| ... | ... | @@ -577,7 +571,7 @@ pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void { |
| 577 | 571 | const global = elf_file.symbol(global_index); |
| 578 | 572 | const file_ptr = global.file(elf_file) orelse continue; |
| 579 | 573 | if (file_ptr.index() != self.index) continue; |
| 580 | if (global.atom(elf_file)) |atom| if (!atom.flags.alive) continue; | |
| 574 | if (global.atom(elf_file)) |atom_ptr| if (!atom_ptr.alive) continue; | |
| 581 | 575 | global.flags.output_symtab = true; |
| 582 | 576 | if (global.isLocal(elf_file)) { |
| 583 | 577 | try global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); |
| ... | ... | @@ -621,11 +615,10 @@ pub fn asFile(self: *ZigObject) File { |
| 621 | 615 | |
| 622 | 616 | /// Returns atom's code. |
| 623 | 617 | /// Caller owns the memory. |
| 624 | pub fn codeAlloc(self: ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 { | |
| 618 | pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 { | |
| 625 | 619 | const gpa = elf_file.base.comp.gpa; |
| 626 | const atom = elf_file.atom(atom_index).?; | |
| 627 | assert(atom.file_index == self.index); | |
| 628 | const shdr = &elf_file.shdrs.items[atom.outputShndx().?]; | |
| 620 | const atom_ptr = self.atom(atom_index).?; | |
| 621 | const shdr = &elf_file.shdrs.items[atom_ptr.output_section_index]; | |
| 629 | 622 | |
| 630 | 623 | if (shdr.sh_flags & elf.SHF_TLS != 0) { |
| 631 | 624 | const tlv = self.tls_variables.get(atom_index).?; |
| ... | ... | @@ -633,13 +626,13 @@ pub fn codeAlloc(self: ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 |
| 633 | 626 | return code; |
| 634 | 627 | } |
| 635 | 628 | |
| 636 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom.value)); | |
| 637 | const size = std.math.cast(usize, atom.size) orelse return error.Overflow; | |
| 629 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); | |
| 630 | const size = std.math.cast(usize, atom_ptr.size) orelse return error.Overflow; | |
| 638 | 631 | const code = try gpa.alloc(u8, size); |
| 639 | 632 | errdefer gpa.free(code); |
| 640 | 633 | const amt = try elf_file.base.file.?.preadAll(code, file_offset); |
| 641 | 634 | if (amt != code.len) { |
| 642 | log.err("fetching code for {s} failed", .{atom.name(elf_file)}); | |
| 635 | log.err("fetching code for {s} failed", .{atom_ptr.name(elf_file)}); | |
| 643 | 636 | return error.InputOutput; |
| 644 | 637 | } |
| 645 | 638 | return code; |
| ... | ... | @@ -760,7 +753,7 @@ pub fn getOrCreateMetadataForLazySymbol( |
| 760 | 753 | }; |
| 761 | 754 | switch (metadata.state.*) { |
| 762 | 755 | .unused => { |
| 763 | const symbol_index = try self.addAtom(elf_file); | |
| 756 | const symbol_index = try self.newAtom(elf_file); | |
| 764 | 757 | const sym = elf_file.symbol(symbol_index); |
| 765 | 758 | sym.flags.needs_zig_got = true; |
| 766 | 759 | metadata.symbol_index.* = symbol_index; |
| ... | ... | @@ -824,7 +817,7 @@ pub fn getOrCreateMetadataForDecl( |
| 824 | 817 | const gop = try self.decls.getOrPut(gpa, decl_index); |
| 825 | 818 | if (!gop.found_existing) { |
| 826 | 819 | const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded; |
| 827 | const symbol_index = try self.addAtom(elf_file); | |
| 820 | const symbol_index = try self.newAtom(elf_file); | |
| 828 | 821 | const mod = elf_file.base.comp.module.?; |
| 829 | 822 | const decl = mod.declPtr(decl_index); |
| 830 | 823 | const sym = elf_file.symbol(symbol_index); |
| ... | ... | @@ -861,14 +854,14 @@ fn getDeclShdrIndex( |
| 861 | 854 | if (is_all_zeroes) break :blk elf_file.sectionByName(".tbss") orelse try elf_file.addSection(.{ |
| 862 | 855 | .type = elf.SHT_NOBITS, |
| 863 | 856 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS, |
| 864 | .name = ".tbss", | |
| 857 | .name = try elf_file.insertShString(".tbss"), | |
| 865 | 858 | .offset = std.math.maxInt(u64), |
| 866 | 859 | }); |
| 867 | 860 | |
| 868 | 861 | break :blk elf_file.sectionByName(".tdata") orelse try elf_file.addSection(.{ |
| 869 | 862 | .type = elf.SHT_PROGBITS, |
| 870 | 863 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS, |
| 871 | .name = ".tdata", | |
| 864 | .name = try elf_file.insertShString(".tdata"), | |
| 872 | 865 | .offset = std.math.maxInt(u64), |
| 873 | 866 | }); |
| 874 | 867 | } |
| ... | ... | @@ -919,14 +912,13 @@ fn updateDeclCode( |
| 919 | 912 | const sym = elf_file.symbol(sym_index); |
| 920 | 913 | const esym = &self.local_esyms.items(.elf_sym)[sym.esym_index]; |
| 921 | 914 | const atom_ptr = sym.atom(elf_file).?; |
| 915 | const name_offset = try self.strtab.insert(gpa, decl.fqn.toSlice(ip)); | |
| 922 | 916 | |
| 923 | sym.output_section_index = shdr_index; | |
| 917 | atom_ptr.alive = true; | |
| 918 | atom_ptr.name_offset = name_offset; | |
| 924 | 919 | atom_ptr.output_section_index = shdr_index; |
| 925 | ||
| 926 | sym.name_offset = try self.strtab.insert(gpa, decl.fqn.toSlice(ip)); | |
| 927 | atom_ptr.flags.alive = true; | |
| 928 | atom_ptr.name_offset = sym.name_offset; | |
| 929 | esym.st_name = sym.name_offset; | |
| 920 | sym.name_offset = name_offset; | |
| 921 | esym.st_name = name_offset; | |
| 930 | 922 | esym.st_info |= stt_bits; |
| 931 | 923 | esym.st_size = code.len; |
| 932 | 924 | |
| ... | ... | @@ -1018,16 +1010,17 @@ fn updateTlv( |
| 1018 | 1010 | const sym = elf_file.symbol(sym_index); |
| 1019 | 1011 | const esym = &self.local_esyms.items(.elf_sym)[sym.esym_index]; |
| 1020 | 1012 | const atom_ptr = sym.atom(elf_file).?; |
| 1013 | const name_offset = try self.strtab.insert(gpa, decl.fqn.toSlice(ip)); | |
| 1021 | 1014 | |
| 1022 | 1015 | sym.value = 0; |
| 1023 | sym.output_section_index = shndx; | |
| 1016 | sym.name_offset = name_offset; | |
| 1017 | ||
| 1024 | 1018 | atom_ptr.output_section_index = shndx; |
| 1019 | atom_ptr.alive = true; | |
| 1020 | atom_ptr.name_offset = name_offset; | |
| 1025 | 1021 | |
| 1026 | sym.name_offset = try self.strtab.insert(gpa, decl.fqn.toSlice(ip)); | |
| 1027 | atom_ptr.flags.alive = true; | |
| 1028 | atom_ptr.name_offset = sym.name_offset; | |
| 1029 | 1022 | esym.st_value = 0; |
| 1030 | esym.st_name = sym.name_offset; | |
| 1023 | esym.st_name = name_offset; | |
| 1031 | 1024 | esym.st_info = elf.STT_TLS; |
| 1032 | 1025 | esym.st_size = code.len; |
| 1033 | 1026 | |
| ... | ... | @@ -1048,7 +1041,7 @@ fn updateTlv( |
| 1048 | 1041 | { |
| 1049 | 1042 | const gop = try elf_file.output_sections.getOrPut(gpa, atom_ptr.output_section_index); |
| 1050 | 1043 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 1051 | try gop.value_ptr.append(gpa, atom_ptr.atom_index); | |
| 1044 | try gop.value_ptr.append(gpa, .{ .index = atom_ptr.atom_index, .file = self.index }); | |
| 1052 | 1045 | } |
| 1053 | 1046 | } |
| 1054 | 1047 | |
| ... | ... | @@ -1242,13 +1235,12 @@ fn updateLazySymbol( |
| 1242 | 1235 | }; |
| 1243 | 1236 | const local_sym = elf_file.symbol(symbol_index); |
| 1244 | 1237 | local_sym.name_offset = name_str_index; |
| 1245 | local_sym.output_section_index = output_section_index; | |
| 1246 | 1238 | const local_esym = &self.local_esyms.items(.elf_sym)[local_sym.esym_index]; |
| 1247 | 1239 | local_esym.st_name = name_str_index; |
| 1248 | 1240 | local_esym.st_info |= elf.STT_OBJECT; |
| 1249 | 1241 | local_esym.st_size = code.len; |
| 1250 | 1242 | const atom_ptr = local_sym.atom(elf_file).?; |
| 1251 | atom_ptr.flags.alive = true; | |
| 1243 | atom_ptr.alive = true; | |
| 1252 | 1244 | atom_ptr.name_offset = name_str_index; |
| 1253 | 1245 | atom_ptr.alignment = required_alignment; |
| 1254 | 1246 | atom_ptr.size = code.len; |
| ... | ... | @@ -1307,8 +1299,7 @@ pub fn lowerUnnamedConst( |
| 1307 | 1299 | return error.CodegenFail; |
| 1308 | 1300 | }, |
| 1309 | 1301 | }; |
| 1310 | const sym = elf_file.symbol(sym_index); | |
| 1311 | try unnamed_consts.append(gpa, sym.atom_index); | |
| 1302 | try unnamed_consts.append(gpa, sym_index); | |
| 1312 | 1303 | return sym_index; |
| 1313 | 1304 | } |
| 1314 | 1305 | |
| ... | ... | @@ -1332,7 +1323,7 @@ fn lowerConst( |
| 1332 | 1323 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 1333 | 1324 | defer code_buffer.deinit(); |
| 1334 | 1325 | |
| 1335 | const sym_index = try self.addAtom(elf_file); | |
| 1326 | const sym_index = try self.newAtom(elf_file); | |
| 1336 | 1327 | |
| 1337 | 1328 | const res = try codegen.generateSymbol( |
| 1338 | 1329 | &elf_file.base, |
| ... | ... | @@ -1351,13 +1342,12 @@ fn lowerConst( |
| 1351 | 1342 | const local_sym = elf_file.symbol(sym_index); |
| 1352 | 1343 | const name_str_index = try self.strtab.insert(gpa, name); |
| 1353 | 1344 | local_sym.name_offset = name_str_index; |
| 1354 | local_sym.output_section_index = output_section_index; | |
| 1355 | 1345 | const local_esym = &self.local_esyms.items(.elf_sym)[local_sym.esym_index]; |
| 1356 | 1346 | local_esym.st_name = name_str_index; |
| 1357 | 1347 | local_esym.st_info |= elf.STT_OBJECT; |
| 1358 | 1348 | local_esym.st_size = code.len; |
| 1359 | 1349 | const atom_ptr = local_sym.atom(elf_file).?; |
| 1360 | atom_ptr.flags.alive = true; | |
| 1350 | atom_ptr.alive = true; | |
| 1361 | 1351 | atom_ptr.name_offset = name_str_index; |
| 1362 | 1352 | atom_ptr.alignment = required_alignment; |
| 1363 | 1353 | atom_ptr.size = code.len; |
| ... | ... | @@ -1530,6 +1520,72 @@ pub fn getString(self: ZigObject, off: u32) [:0]const u8 { |
| 1530 | 1520 | return self.strtab.getAssumeExists(off); |
| 1531 | 1521 | } |
| 1532 | 1522 | |
| 1523 | fn addAtom(self: *ZigObject, allocator: Allocator) !Atom.Index { | |
| 1524 | try self.atoms.ensureUnusedCapacity(allocator, 1); | |
| 1525 | try self.atoms_extra.ensureUnusedCapacity(allocator, @sizeOf(Atom.Extra)); | |
| 1526 | return self.addAtomAssumeCapacity(); | |
| 1527 | } | |
| 1528 | ||
| 1529 | fn addAtomAssumeCapacity(self: *ZigObject) Atom.Index { | |
| 1530 | const atom_index: Atom.Index = @intCast(self.atoms.items.len); | |
| 1531 | const atom_ptr = self.atoms.addOneAssumeCapacity(); | |
| 1532 | atom_ptr.* = .{ | |
| 1533 | .file_index = self.index, | |
| 1534 | .atom_index = atom_index, | |
| 1535 | .extra_index = self.addAtomExtraAssumeCapacity(.{}), | |
| 1536 | }; | |
| 1537 | return atom_index; | |
| 1538 | } | |
| 1539 | ||
| 1540 | pub fn atom(self: *ZigObject, atom_index: Atom.Index) ?*Atom { | |
| 1541 | if (atom_index == 0) return null; | |
| 1542 | assert(atom_index < self.atoms.items.len); | |
| 1543 | return &self.atoms.items[atom_index]; | |
| 1544 | } | |
| 1545 | ||
| 1546 | fn addAtomExtra(self: *ZigObject, allocator: Allocator, extra: Atom.Extra) !u32 { | |
| 1547 | const fields = @typeInfo(Atom.Extra).Struct.fields; | |
| 1548 | try self.atoms_extra.ensureUnusedCapacity(allocator, fields.len); | |
| 1549 | return self.addAtomExtraAssumeCapacity(extra); | |
| 1550 | } | |
| 1551 | ||
| 1552 | fn addAtomExtraAssumeCapacity(self: *ZigObject, extra: Atom.Extra) u32 { | |
| 1553 | const index = @as(u32, @intCast(self.atoms_extra.items.len)); | |
| 1554 | const fields = @typeInfo(Atom.Extra).Struct.fields; | |
| 1555 | inline for (fields) |field| { | |
| 1556 | self.atoms_extra.appendAssumeCapacity(switch (field.type) { | |
| 1557 | u32 => @field(extra, field.name), | |
| 1558 | else => @compileError("bad field type"), | |
| 1559 | }); | |
| 1560 | } | |
| 1561 | return index; | |
| 1562 | } | |
| 1563 | ||
| 1564 | pub fn atomExtra(self: ZigObject, index: u32) Atom.Extra { | |
| 1565 | const fields = @typeInfo(Atom.Extra).Struct.fields; | |
| 1566 | var i: usize = index; | |
| 1567 | var result: Atom.Extra = undefined; | |
| 1568 | inline for (fields) |field| { | |
| 1569 | @field(result, field.name) = switch (field.type) { | |
| 1570 | u32 => self.atoms_extra.items[i], | |
| 1571 | else => @compileError("bad field type"), | |
| 1572 | }; | |
| 1573 | i += 1; | |
| 1574 | } | |
| 1575 | return result; | |
| 1576 | } | |
| 1577 | ||
| 1578 | pub fn setAtomExtra(self: *ZigObject, index: u32, extra: Atom.Extra) void { | |
| 1579 | assert(index > 0); | |
| 1580 | const fields = @typeInfo(Atom.Extra).Struct.fields; | |
| 1581 | inline for (fields, 0..) |field, i| { | |
| 1582 | self.atoms_extra.items[index + i] = switch (field.type) { | |
| 1583 | u32 => @field(extra, field.name), | |
| 1584 | else => @compileError("bad field type"), | |
| 1585 | }; | |
| 1586 | } | |
| 1587 | } | |
| 1588 | ||
| 1533 | 1589 | pub fn fmtSymtab(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(formatSymtab) { |
| 1534 | 1590 | return .{ .data = .{ |
| 1535 | 1591 | .self = self, |
| ... | ... | @@ -1578,9 +1634,9 @@ fn formatAtoms( |
| 1578 | 1634 | _ = unused_fmt_string; |
| 1579 | 1635 | _ = options; |
| 1580 | 1636 | try writer.writeAll(" atoms\n"); |
| 1581 | for (ctx.self.atoms.items) |atom_index| { | |
| 1582 | const atom = ctx.elf_file.atom(atom_index) orelse continue; | |
| 1583 | try writer.print(" {}\n", .{atom.fmt(ctx.elf_file)}); | |
| 1637 | for (ctx.self.atoms_indexes.items) |atom_index| { | |
| 1638 | const atom_ptr = ctx.self.atom(atom_index) orelse continue; | |
| 1639 | try writer.print(" {}\n", .{atom_ptr.fmt(ctx.elf_file)}); | |
| 1584 | 1640 | } |
| 1585 | 1641 | } |
| 1586 | 1642 |
src/link/Elf/eh_frame.zig+3-3| ... | ... | @@ -42,8 +42,8 @@ pub const Fde = struct { |
| 42 | 42 | const object = elf_file.file(fde.file_index).?.object; |
| 43 | 43 | const rel = fde.relocs(elf_file)[0]; |
| 44 | 44 | const sym = object.symtab.items[rel.r_sym()]; |
| 45 | const atom_index = object.atoms.items[sym.st_shndx]; | |
| 46 | return elf_file.atom(atom_index).?; | |
| 45 | const atom_index = object.atoms_indexes.items[sym.st_shndx]; | |
| 46 | return object.atom(atom_index).?; | |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | 49 | pub fn relocs(fde: Fde, elf_file: *Elf) []align(1) const elf.Elf64_Rela { |
| ... | ... | @@ -421,7 +421,7 @@ fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Re |
| 421 | 421 | switch (sym.type(elf_file)) { |
| 422 | 422 | elf.STT_SECTION => { |
| 423 | 423 | r_addend += @intCast(sym.address(.{}, elf_file)); |
| 424 | r_sym = elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx().?); | |
| 424 | r_sym = elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx(elf_file).?); | |
| 425 | 425 | }, |
| 426 | 426 | else => { |
| 427 | 427 | r_sym = sym.outputSymtabIndex(elf_file) orelse 0; |
src/link/Elf/file.zig+39-3| ... | ... | @@ -98,11 +98,34 @@ pub const File = union(enum) { |
| 98 | 98 | } |
| 99 | 99 | } |
| 100 | 100 | |
| 101 | pub fn atom(file: File, atom_index: Atom.Index) ?*Atom { | |
| 102 | return switch (file) { | |
| 103 | .shared_object => unreachable, | |
| 104 | .linker_defined => null, | |
| 105 | inline else => |x| x.atom(atom_index), | |
| 106 | }; | |
| 107 | } | |
| 108 | ||
| 101 | 109 | pub fn atoms(file: File) []const Atom.Index { |
| 102 | 110 | return switch (file) { |
| 103 | .linker_defined, .shared_object => &[0]Atom.Index{}, | |
| 104 | .zig_object => |x| x.atoms.items, | |
| 105 | .object => |x| x.atoms.items, | |
| 111 | .shared_object => unreachable, | |
| 112 | .linker_defined => &[0]Atom.Index{}, | |
| 113 | .zig_object => |x| x.atoms_indexes.items, | |
| 114 | .object => |x| x.atoms_indexes.items, | |
| 115 | }; | |
| 116 | } | |
| 117 | ||
| 118 | pub fn atomExtra(file: File, extra_index: u32) Atom.Extra { | |
| 119 | return switch (file) { | |
| 120 | .shared_object, .linker_defined => unreachable, | |
| 121 | inline else => |x| x.atomExtra(extra_index), | |
| 122 | }; | |
| 123 | } | |
| 124 | ||
| 125 | pub fn setAtomExtra(file: File, extra_index: u32, extra: Atom.Extra) void { | |
| 126 | return switch (file) { | |
| 127 | .shared_object, .linker_defined => unreachable, | |
| 128 | inline else => |x| x.setAtomExtra(extra_index, extra), | |
| 106 | 129 | }; |
| 107 | 130 | } |
| 108 | 131 | |
| ... | ... | @@ -114,6 +137,13 @@ pub const File = union(enum) { |
| 114 | 137 | }; |
| 115 | 138 | } |
| 116 | 139 | |
| 140 | pub fn comdatGroup(file: File, ind: Elf.ComdatGroup.Index) *Elf.ComdatGroup { | |
| 141 | return switch (file) { | |
| 142 | .linker_defined, .shared_object, .zig_object => unreachable, | |
| 143 | .object => |x| x.comdatGroup(ind), | |
| 144 | }; | |
| 145 | } | |
| 146 | ||
| 117 | 147 | pub fn symbol(file: File, ind: Symbol.Index) Symbol.Index { |
| 118 | 148 | return switch (file) { |
| 119 | 149 | .zig_object => |x| x.symbol(ind), |
| ... | ... | @@ -134,6 +164,12 @@ pub const File = union(enum) { |
| 134 | 164 | }; |
| 135 | 165 | } |
| 136 | 166 | |
| 167 | pub fn getString(file: File, off: u32) [:0]const u8 { | |
| 168 | return switch (file) { | |
| 169 | inline else => |x| x.getString(off), | |
| 170 | }; | |
| 171 | } | |
| 172 | ||
| 137 | 173 | pub fn updateSymtabSize(file: File, elf_file: *Elf) !void { |
| 138 | 174 | return switch (file) { |
| 139 | 175 | inline else => |x| x.updateSymtabSize(elf_file), |
src/link/Elf/gc.zig+23-19| ... | ... | @@ -16,9 +16,11 @@ pub fn gcAtoms(elf_file: *Elf) !void { |
| 16 | 16 | } |
| 17 | 17 | |
| 18 | 18 | fn collectRoots(roots: *std.ArrayList(*Atom), files: []const File.Index, elf_file: *Elf) !void { |
| 19 | if (elf_file.entry_index) |index| { | |
| 20 | const global = elf_file.symbol(index); | |
| 21 | try markSymbol(global, roots, elf_file); | |
| 19 | if (elf_file.linkerDefinedPtr()) |obj| { | |
| 20 | if (obj.entry_index) |index| { | |
| 21 | const global = elf_file.symbol(index); | |
| 22 | try markSymbol(global, roots, elf_file); | |
| 23 | } | |
| 22 | 24 | } |
| 23 | 25 | |
| 24 | 26 | for (files) |index| { |
| ... | ... | @@ -35,8 +37,8 @@ fn collectRoots(roots: *std.ArrayList(*Atom), files: []const File.Index, elf_fil |
| 35 | 37 | const file = elf_file.file(index).?; |
| 36 | 38 | |
| 37 | 39 | for (file.atoms()) |atom_index| { |
| 38 | const atom = elf_file.atom(atom_index) orelse continue; | |
| 39 | if (!atom.flags.alive) continue; | |
| 40 | const atom = file.atom(atom_index) orelse continue; | |
| 41 | if (!atom.alive) continue; | |
| 40 | 42 | |
| 41 | 43 | const shdr = atom.inputShdr(elf_file); |
| 42 | 44 | const name = atom.name(elf_file); |
| ... | ... | @@ -54,7 +56,7 @@ fn collectRoots(roots: *std.ArrayList(*Atom), files: []const File.Index, elf_fil |
| 54 | 56 | break :blk false; |
| 55 | 57 | }; |
| 56 | 58 | if (is_gc_root and markAtom(atom)) try roots.append(atom); |
| 57 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) atom.flags.visited = true; | |
| 59 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) atom.visited = true; | |
| 58 | 60 | } |
| 59 | 61 | |
| 60 | 62 | // Mark every atom referenced by CIE as alive. |
| ... | ... | @@ -77,22 +79,22 @@ fn markSymbol(sym: *Symbol, roots: *std.ArrayList(*Atom), elf_file: *Elf) !void |
| 77 | 79 | } |
| 78 | 80 | |
| 79 | 81 | fn markAtom(atom: *Atom) bool { |
| 80 | const already_visited = atom.flags.visited; | |
| 81 | atom.flags.visited = true; | |
| 82 | return atom.flags.alive and !already_visited; | |
| 82 | const already_visited = atom.visited; | |
| 83 | atom.visited = true; | |
| 84 | return atom.alive and !already_visited; | |
| 83 | 85 | } |
| 84 | 86 | |
| 85 | 87 | fn markLive(atom: *Atom, elf_file: *Elf) void { |
| 86 | 88 | if (@import("build_options").enable_logging) track_live_level.incr(); |
| 87 | 89 | |
| 88 | assert(atom.flags.visited); | |
| 90 | assert(atom.visited); | |
| 89 | 91 | const file = atom.file(elf_file).?; |
| 90 | 92 | |
| 91 | 93 | for (atom.fdes(elf_file)) |fde| { |
| 92 | 94 | for (fde.relocs(elf_file)[1..]) |rel| { |
| 93 | 95 | const target_sym = elf_file.symbol(file.symbol(rel.r_sym())); |
| 94 | 96 | const target_atom = target_sym.atom(elf_file) orelse continue; |
| 95 | target_atom.flags.alive = true; | |
| 97 | target_atom.alive = true; | |
| 96 | 98 | gc_track_live_log.debug("{}marking live atom({d})", .{ track_live_level, target_atom.atom_index }); |
| 97 | 99 | if (markAtom(target_atom)) markLive(target_atom, elf_file); |
| 98 | 100 | } |
| ... | ... | @@ -105,7 +107,7 @@ fn markLive(atom: *Atom, elf_file: *Elf) void { |
| 105 | 107 | continue; |
| 106 | 108 | } |
| 107 | 109 | const target_atom = target_sym.atom(elf_file) orelse continue; |
| 108 | target_atom.flags.alive = true; | |
| 110 | target_atom.alive = true; | |
| 109 | 111 | gc_track_live_log.debug("{}marking live atom({d})", .{ track_live_level, target_atom.atom_index }); |
| 110 | 112 | if (markAtom(target_atom)) markLive(target_atom, elf_file); |
| 111 | 113 | } |
| ... | ... | @@ -120,10 +122,11 @@ fn mark(roots: std.ArrayList(*Atom), elf_file: *Elf) void { |
| 120 | 122 | |
| 121 | 123 | fn prune(files: []const File.Index, elf_file: *Elf) void { |
| 122 | 124 | for (files) |index| { |
| 123 | for (elf_file.file(index).?.atoms()) |atom_index| { | |
| 124 | const atom = elf_file.atom(atom_index) orelse continue; | |
| 125 | if (atom.flags.alive and !atom.flags.visited) { | |
| 126 | atom.flags.alive = false; | |
| 125 | const file = elf_file.file(index).?; | |
| 126 | for (file.atoms()) |atom_index| { | |
| 127 | const atom = file.atom(atom_index) orelse continue; | |
| 128 | if (atom.alive and !atom.visited) { | |
| 129 | atom.alive = false; | |
| 127 | 130 | atom.markFdesDead(elf_file); |
| 128 | 131 | } |
| 129 | 132 | } |
| ... | ... | @@ -133,9 +136,10 @@ fn prune(files: []const File.Index, elf_file: *Elf) void { |
| 133 | 136 | pub fn dumpPrunedAtoms(elf_file: *Elf) !void { |
| 134 | 137 | const stderr = std.io.getStdErr().writer(); |
| 135 | 138 | for (elf_file.objects.items) |index| { |
| 136 | for (elf_file.file(index).?.object.atoms.items) |atom_index| { | |
| 137 | const atom = elf_file.atom(atom_index) orelse continue; | |
| 138 | if (!atom.flags.alive) | |
| 139 | const file = elf_file.file(index).?; | |
| 140 | for (file.atoms()) |atom_index| { | |
| 141 | const atom = file.atom(atom_index) orelse continue; | |
| 142 | if (!atom.alive) | |
| 139 | 143 | // TODO should we simply print to stderr? |
| 140 | 144 | try stderr.print("link: removing unused section '{s}' in file '{}'\n", .{ |
| 141 | 145 | atom.name(elf_file), |
src/link/Elf/merge_section.zig+40-17| ... | ... | @@ -10,16 +10,18 @@ pub const MergeSection = struct { |
| 10 | 10 | IndexContext, |
| 11 | 11 | std.hash_map.default_max_load_percentage, |
| 12 | 12 | ) = .{}, |
| 13 | subsections: std.ArrayListUnmanaged(MergeSubsection.Index) = .{}, | |
| 13 | subsections: std.ArrayListUnmanaged(MergeSubsection) = .{}, | |
| 14 | finalized_subsections: std.ArrayListUnmanaged(MergeSubsection.Index) = .{}, | |
| 14 | 15 | |
| 15 | 16 | pub fn deinit(msec: *MergeSection, allocator: Allocator) void { |
| 16 | 17 | msec.bytes.deinit(allocator); |
| 17 | 18 | msec.table.deinit(allocator); |
| 18 | 19 | msec.subsections.deinit(allocator); |
| 20 | msec.finalized_subsections.deinit(allocator); | |
| 19 | 21 | } |
| 20 | 22 | |
| 21 | 23 | pub fn name(msec: MergeSection, elf_file: *Elf) [:0]const u8 { |
| 22 | return elf_file.strings.getAssumeExists(msec.name_offset); | |
| 24 | return elf_file.getShString(msec.name_offset); | |
| 23 | 25 | } |
| 24 | 26 | |
| 25 | 27 | pub fn address(msec: MergeSection, elf_file: *Elf) i64 { |
| ... | ... | @@ -58,25 +60,26 @@ pub const MergeSection = struct { |
| 58 | 60 | |
| 59 | 61 | /// Finalizes the merge section and clears hash table. |
| 60 | 62 | /// Sorts all owned subsections. |
| 61 | pub fn finalize(msec: *MergeSection, elf_file: *Elf) !void { | |
| 62 | const gpa = elf_file.base.comp.gpa; | |
| 63 | try msec.subsections.ensureTotalCapacityPrecise(gpa, msec.table.count()); | |
| 63 | pub fn finalize(msec: *MergeSection, allocator: Allocator) !void { | |
| 64 | try msec.finalized_subsections.ensureTotalCapacityPrecise(allocator, msec.subsections.items.len); | |
| 64 | 65 | |
| 65 | 66 | var it = msec.table.iterator(); |
| 66 | 67 | while (it.next()) |entry| { |
| 67 | const msub = elf_file.mergeSubsection(entry.value_ptr.*); | |
| 68 | const msub = msec.mergeSubsection(entry.value_ptr.*); | |
| 68 | 69 | if (!msub.alive) continue; |
| 69 | msec.subsections.appendAssumeCapacity(entry.value_ptr.*); | |
| 70 | msec.finalized_subsections.appendAssumeCapacity(entry.value_ptr.*); | |
| 70 | 71 | } |
| 71 | msec.table.clearAndFree(gpa); | |
| 72 | msec.table.clearAndFree(allocator); | |
| 72 | 73 | |
| 73 | 74 | const sortFn = struct { |
| 74 | pub fn sortFn(ctx: *Elf, lhs: MergeSubsection.Index, rhs: MergeSubsection.Index) bool { | |
| 75 | pub fn sortFn(ctx: *MergeSection, lhs: MergeSubsection.Index, rhs: MergeSubsection.Index) bool { | |
| 75 | 76 | const lhs_msub = ctx.mergeSubsection(lhs); |
| 76 | 77 | const rhs_msub = ctx.mergeSubsection(rhs); |
| 77 | 78 | if (lhs_msub.alignment.compareStrict(.eq, rhs_msub.alignment)) { |
| 78 | 79 | if (lhs_msub.size == rhs_msub.size) { |
| 79 | return mem.order(u8, lhs_msub.getString(ctx), rhs_msub.getString(ctx)) == .lt; | |
| 80 | const lhs_string = ctx.bytes.items[lhs_msub.string_index..][0..lhs_msub.size]; | |
| 81 | const rhs_string = ctx.bytes.items[rhs_msub.string_index..][0..rhs_msub.size]; | |
| 82 | return mem.order(u8, lhs_string, rhs_string) == .lt; | |
| 80 | 83 | } |
| 81 | 84 | return lhs_msub.size < rhs_msub.size; |
| 82 | 85 | } |
| ... | ... | @@ -84,7 +87,19 @@ pub const MergeSection = struct { |
| 84 | 87 | } |
| 85 | 88 | }.sortFn; |
| 86 | 89 | |
| 87 | std.mem.sort(MergeSubsection.Index, msec.subsections.items, elf_file, sortFn); | |
| 90 | std.mem.sort(MergeSubsection.Index, msec.finalized_subsections.items, msec, sortFn); | |
| 91 | } | |
| 92 | ||
| 93 | pub fn addMergeSubsection(msec: *MergeSection, allocator: Allocator) !MergeSubsection.Index { | |
| 94 | const index: MergeSubsection.Index = @intCast(msec.subsections.items.len); | |
| 95 | const msub = try msec.subsections.addOne(allocator); | |
| 96 | msub.* = .{}; | |
| 97 | return index; | |
| 98 | } | |
| 99 | ||
| 100 | pub fn mergeSubsection(msec: *MergeSection, index: MergeSubsection.Index) *MergeSubsection { | |
| 101 | assert(index < msec.subsections.items.len); | |
| 102 | return &msec.subsections.items[index]; | |
| 88 | 103 | } |
| 89 | 104 | |
| 90 | 105 | pub const IndexContext = struct { |
| ... | ... | @@ -154,8 +169,8 @@ pub const MergeSection = struct { |
| 154 | 169 | msec.type, |
| 155 | 170 | msec.flags, |
| 156 | 171 | }); |
| 157 | for (msec.subsections.items) |index| { | |
| 158 | try writer.print(" {}\n", .{elf_file.mergeSubsection(index).fmt(elf_file)}); | |
| 172 | for (msec.subsections.items) |msub| { | |
| 173 | try writer.print(" {}\n", .{msub.fmt(elf_file)}); | |
| 159 | 174 | } |
| 160 | 175 | } |
| 161 | 176 | |
| ... | ... | @@ -250,18 +265,26 @@ pub const InputMergeSection = struct { |
| 250 | 265 | // TODO: imsec.strings.clearAndFree(allocator); |
| 251 | 266 | } |
| 252 | 267 | |
| 253 | pub fn findSubsection(imsec: InputMergeSection, offset: u32) ?struct { MergeSubsection.Index, u32 } { | |
| 268 | const FindSubsectionResult = struct { | |
| 269 | msub_index: MergeSubsection.Index, | |
| 270 | offset: u32, | |
| 271 | }; | |
| 272 | ||
| 273 | pub fn findSubsection(imsec: InputMergeSection, offset: u32) ?FindSubsectionResult { | |
| 254 | 274 | // TODO: binary search |
| 255 | 275 | for (imsec.offsets.items, 0..) |off, index| { |
| 256 | 276 | if (offset < off) return .{ |
| 257 | imsec.subsections.items[index - 1], | |
| 258 | offset - imsec.offsets.items[index - 1], | |
| 277 | .msub_index = imsec.subsections.items[index - 1], | |
| 278 | .offset = offset - imsec.offsets.items[index - 1], | |
| 259 | 279 | }; |
| 260 | 280 | } |
| 261 | 281 | const last = imsec.offsets.items.len - 1; |
| 262 | 282 | const last_off = imsec.offsets.items[last]; |
| 263 | 283 | const last_len = imsec.strings.items[last].len; |
| 264 | if (offset < last_off + last_len) return .{ imsec.subsections.items[last], offset - last_off }; | |
| 284 | if (offset < last_off + last_len) return .{ | |
| 285 | .msub_index = imsec.subsections.items[last], | |
| 286 | .offset = offset - last_off, | |
| 287 | }; | |
| 265 | 288 | return null; |
| 266 | 289 | } |
| 267 | 290 |
src/link/Elf/relocatable.zig+27-28| ... | ... | @@ -190,7 +190,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 190 | 190 | // Now, we are ready to resolve the symbols across all input files. |
| 191 | 191 | // We will first resolve the files in the ZigObject, next in the parsed |
| 192 | 192 | // input Object files. |
| 193 | elf_file.resolveSymbols(); | |
| 193 | try elf_file.resolveSymbols(); | |
| 194 | 194 | elf_file.markEhFrameAtomsDead(); |
| 195 | 195 | try elf_file.resolveMergeSections(); |
| 196 | 196 | try elf_file.addCommentString(); |
| ... | ... | @@ -299,13 +299,16 @@ fn initSections(elf_file: *Elf) !void { |
| 299 | 299 | } else false; |
| 300 | 300 | if (needs_eh_frame) { |
| 301 | 301 | elf_file.eh_frame_section_index = try elf_file.addSection(.{ |
| 302 | .name = ".eh_frame", | |
| 302 | .name = try elf_file.insertShString(".eh_frame"), | |
| 303 | 303 | .type = elf.SHT_PROGBITS, |
| 304 | 304 | .flags = elf.SHF_ALLOC, |
| 305 | 305 | .addralign = ptr_size, |
| 306 | 306 | .offset = std.math.maxInt(u64), |
| 307 | 307 | }); |
| 308 | elf_file.eh_frame_rela_section_index = try elf_file.addRelaShdr(".rela.eh_frame", elf_file.eh_frame_section_index.?); | |
| 308 | elf_file.eh_frame_rela_section_index = try elf_file.addRelaShdr( | |
| 309 | try elf_file.insertShString(".rela.eh_frame"), | |
| 310 | elf_file.eh_frame_section_index.?, | |
| 311 | ); | |
| 309 | 312 | } |
| 310 | 313 | |
| 311 | 314 | try initComdatGroups(elf_file); |
| ... | ... | @@ -318,22 +321,18 @@ fn initComdatGroups(elf_file: *Elf) !void { |
| 318 | 321 | |
| 319 | 322 | for (elf_file.objects.items) |index| { |
| 320 | 323 | const object = elf_file.file(index).?.object; |
| 321 | ||
| 322 | for (object.comdat_groups.items) |cg_index| { | |
| 323 | const cg = elf_file.comdatGroup(cg_index); | |
| 324 | const cg_owner = elf_file.comdatGroupOwner(cg.owner); | |
| 325 | if (cg_owner.file != index) continue; | |
| 326 | ||
| 324 | for (object.comdat_groups.items, 0..) |cg, cg_index| { | |
| 325 | if (!cg.alive) continue; | |
| 327 | 326 | const cg_sec = try elf_file.comdat_group_sections.addOne(gpa); |
| 328 | 327 | cg_sec.* = .{ |
| 329 | 328 | .shndx = try elf_file.addSection(.{ |
| 330 | .name = ".group", | |
| 329 | .name = try elf_file.insertShString(".group"), | |
| 331 | 330 | .type = elf.SHT_GROUP, |
| 332 | 331 | .entsize = @sizeOf(u32), |
| 333 | 332 | .addralign = @alignOf(u32), |
| 334 | 333 | .offset = std.math.maxInt(u64), |
| 335 | 334 | }), |
| 336 | .cg_index = cg_index, | |
| 335 | .cg_ref = .{ .index = @intCast(cg_index), .file = index }, | |
| 337 | 336 | }; |
| 338 | 337 | } |
| 339 | 338 | } |
| ... | ... | @@ -342,9 +341,9 @@ fn initComdatGroups(elf_file: *Elf) !void { |
| 342 | 341 | fn updateSectionSizes(elf_file: *Elf) !void { |
| 343 | 342 | for (elf_file.output_sections.keys(), elf_file.output_sections.values()) |shndx, atom_list| { |
| 344 | 343 | const shdr = &elf_file.shdrs.items[shndx]; |
| 345 | for (atom_list.items) |atom_index| { | |
| 346 | const atom_ptr = elf_file.atom(atom_index) orelse continue; | |
| 347 | if (!atom_ptr.flags.alive) continue; | |
| 344 | for (atom_list.items) |ref| { | |
| 345 | const atom_ptr = elf_file.atom(ref) orelse continue; | |
| 346 | if (!atom_ptr.alive) continue; | |
| 348 | 347 | const offset = atom_ptr.alignment.forward(shdr.sh_size); |
| 349 | 348 | const padding = offset - shdr.sh_size; |
| 350 | 349 | atom_ptr.value = @intCast(offset); |
| ... | ... | @@ -355,9 +354,9 @@ fn updateSectionSizes(elf_file: *Elf) !void { |
| 355 | 354 | |
| 356 | 355 | for (elf_file.output_rela_sections.values()) |sec| { |
| 357 | 356 | const shdr = &elf_file.shdrs.items[sec.shndx]; |
| 358 | for (sec.atom_list.items) |atom_index| { | |
| 359 | const atom_ptr = elf_file.atom(atom_index) orelse continue; | |
| 360 | if (!atom_ptr.flags.alive) continue; | |
| 357 | for (sec.atom_list.items) |ref| { | |
| 358 | const atom_ptr = elf_file.atom(ref) orelse continue; | |
| 359 | if (!atom_ptr.alive) continue; | |
| 361 | 360 | const relocs = atom_ptr.relocs(elf_file); |
| 362 | 361 | shdr.sh_size += shdr.sh_entsize * relocs.len; |
| 363 | 362 | } |
| ... | ... | @@ -386,7 +385,7 @@ fn updateComdatGroupsSizes(elf_file: *Elf) void { |
| 386 | 385 | |
| 387 | 386 | const sym = elf_file.symbol(cg.symbol(elf_file)); |
| 388 | 387 | shdr.sh_info = sym.outputSymtabIndex(elf_file) orelse |
| 389 | elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx().?); | |
| 388 | elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx(elf_file).?); | |
| 390 | 389 | } |
| 391 | 390 | } |
| 392 | 391 | |
| ... | ... | @@ -449,16 +448,16 @@ fn writeAtoms(elf_file: *Elf) !void { |
| 449 | 448 | 0; |
| 450 | 449 | @memset(buffer, padding_byte); |
| 451 | 450 | |
| 452 | for (atom_list.items) |atom_index| { | |
| 453 | const atom_ptr = elf_file.atom(atom_index).?; | |
| 454 | assert(atom_ptr.flags.alive); | |
| 451 | for (atom_list.items) |ref| { | |
| 452 | const atom_ptr = elf_file.atom(ref).?; | |
| 453 | assert(atom_ptr.alive); | |
| 455 | 454 | |
| 456 | 455 | const offset = math.cast(usize, atom_ptr.value - @as(i64, @intCast(shdr.sh_addr - base_offset))) orelse |
| 457 | 456 | return error.Overflow; |
| 458 | 457 | const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow; |
| 459 | 458 | |
| 460 | log.debug("writing atom({d}) from 0x{x} to 0x{x}", .{ | |
| 461 | atom_index, | |
| 459 | log.debug("writing atom({}) from 0x{x} to 0x{x}", .{ | |
| 460 | ref, | |
| 462 | 461 | sh_offset + offset, |
| 463 | 462 | sh_offset + offset + size, |
| 464 | 463 | }); |
| ... | ... | @@ -466,8 +465,8 @@ fn writeAtoms(elf_file: *Elf) !void { |
| 466 | 465 | // TODO decompress directly into provided buffer |
| 467 | 466 | const out_code = buffer[offset..][0..size]; |
| 468 | 467 | const in_code = switch (atom_ptr.file(elf_file).?) { |
| 469 | .object => |x| try x.codeDecompressAlloc(elf_file, atom_index), | |
| 470 | .zig_object => |x| try x.codeAlloc(elf_file, atom_index), | |
| 468 | .object => |x| try x.codeDecompressAlloc(elf_file, ref.index), | |
| 469 | .zig_object => |x| try x.codeAlloc(elf_file, ref.index), | |
| 471 | 470 | else => unreachable, |
| 472 | 471 | }; |
| 473 | 472 | defer gpa.free(in_code); |
| ... | ... | @@ -491,9 +490,9 @@ fn writeSyntheticSections(elf_file: *Elf) !void { |
| 491 | 490 | var relocs = try std.ArrayList(elf.Elf64_Rela).initCapacity(gpa, num_relocs); |
| 492 | 491 | defer relocs.deinit(); |
| 493 | 492 | |
| 494 | for (sec.atom_list.items) |atom_index| { | |
| 495 | const atom_ptr = elf_file.atom(atom_index) orelse continue; | |
| 496 | if (!atom_ptr.flags.alive) continue; | |
| 493 | for (sec.atom_list.items) |ref| { | |
| 494 | const atom_ptr = elf_file.atom(ref) orelse continue; | |
| 495 | if (!atom_ptr.alive) continue; | |
| 497 | 496 | try atom_ptr.writeRelocs(elf_file, &relocs); |
| 498 | 497 | } |
| 499 | 498 | assert(relocs.items.len == num_relocs); |
src/link/Elf/synthetic_sections.zig+16-17| ... | ... | @@ -1075,7 +1075,7 @@ pub const GotPltSection = struct { |
| 1075 | 1075 | _ = got_plt; |
| 1076 | 1076 | { |
| 1077 | 1077 | // [0]: _DYNAMIC |
| 1078 | const symbol = elf_file.symbol(elf_file.dynamic_index.?); | |
| 1078 | const symbol = elf_file.symbol(elf_file.linkerDefinedPtr().?.dynamic_index.?); | |
| 1079 | 1079 | try writer.writeInt(u64, @intCast(symbol.address(.{}, elf_file)), .little); |
| 1080 | 1080 | } |
| 1081 | 1081 | // [1]: 0x0 |
| ... | ... | @@ -1670,45 +1670,44 @@ pub const VerneedSection = struct { |
| 1670 | 1670 | |
| 1671 | 1671 | pub const ComdatGroupSection = struct { |
| 1672 | 1672 | shndx: u32, |
| 1673 | cg_index: u32, | |
| 1673 | cg_ref: Elf.Ref, | |
| 1674 | 1674 | |
| 1675 | fn file(cgs: ComdatGroupSection, elf_file: *Elf) ?File { | |
| 1676 | const cg = elf_file.comdatGroup(cgs.cg_index); | |
| 1677 | const cg_owner = elf_file.comdatGroupOwner(cg.owner); | |
| 1678 | return elf_file.file(cg_owner.file); | |
| 1675 | fn comdatGroup(cgs: ComdatGroupSection, elf_file: *Elf) *Elf.ComdatGroup { | |
| 1676 | const cg_file = elf_file.file(cgs.cg_ref.file).?; | |
| 1677 | return cg_file.object.comdatGroup(cgs.cg_ref.index); | |
| 1679 | 1678 | } |
| 1680 | 1679 | |
| 1681 | 1680 | pub fn symbol(cgs: ComdatGroupSection, elf_file: *Elf) Symbol.Index { |
| 1682 | const cg = elf_file.comdatGroup(cgs.cg_index); | |
| 1683 | const object = cgs.file(elf_file).?.object; | |
| 1681 | const cg = cgs.comdatGroup(elf_file); | |
| 1682 | const object = cg.file(elf_file).object; | |
| 1684 | 1683 | const shdr = object.shdrs.items[cg.shndx]; |
| 1685 | 1684 | return object.symbols.items[shdr.sh_info]; |
| 1686 | 1685 | } |
| 1687 | 1686 | |
| 1688 | 1687 | pub fn size(cgs: ComdatGroupSection, elf_file: *Elf) usize { |
| 1689 | const cg = elf_file.comdatGroup(cgs.cg_index); | |
| 1688 | const cg = cgs.comdatGroup(elf_file); | |
| 1690 | 1689 | const members = cg.comdatGroupMembers(elf_file); |
| 1691 | 1690 | return (members.len + 1) * @sizeOf(u32); |
| 1692 | 1691 | } |
| 1693 | 1692 | |
| 1694 | 1693 | pub fn write(cgs: ComdatGroupSection, elf_file: *Elf, writer: anytype) !void { |
| 1695 | const cg = elf_file.comdatGroup(cgs.cg_index); | |
| 1696 | const object = cgs.file(elf_file).?.object; | |
| 1694 | const cg = cgs.comdatGroup(elf_file); | |
| 1695 | const object = cg.file(elf_file).object; | |
| 1697 | 1696 | const members = cg.comdatGroupMembers(elf_file); |
| 1698 | 1697 | try writer.writeInt(u32, elf.GRP_COMDAT, .little); |
| 1699 | 1698 | for (members) |shndx| { |
| 1700 | 1699 | const shdr = object.shdrs.items[shndx]; |
| 1701 | 1700 | switch (shdr.sh_type) { |
| 1702 | 1701 | elf.SHT_RELA => { |
| 1703 | const atom_index = object.atoms.items[shdr.sh_info]; | |
| 1704 | const atom = elf_file.atom(atom_index).?; | |
| 1705 | const rela = elf_file.output_rela_sections.get(atom.outputShndx().?).?; | |
| 1702 | const atom_index = object.atoms_indexes.items[shdr.sh_info]; | |
| 1703 | const atom = object.atom(atom_index).?; | |
| 1704 | const rela = elf_file.output_rela_sections.get(atom.output_section_index).?; | |
| 1706 | 1705 | try writer.writeInt(u32, rela.shndx, .little); |
| 1707 | 1706 | }, |
| 1708 | 1707 | else => { |
| 1709 | const atom_index = object.atoms.items[shndx]; | |
| 1710 | const atom = elf_file.atom(atom_index).?; | |
| 1711 | try writer.writeInt(u32, atom.outputShndx().?, .little); | |
| 1708 | const atom_index = object.atoms_indexes.items[shndx]; | |
| 1709 | const atom = object.atom(atom_index).?; | |
| 1710 | try writer.writeInt(u32, atom.output_section_index, .little); | |
| 1712 | 1711 | }, |
| 1713 | 1712 | } |
| 1714 | 1713 | } |
src/link/Elf/thunks.zig+9-11| ... | ... | @@ -6,22 +6,21 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void { |
| 6 | 6 | const atoms = elf_file.output_sections.get(shndx).?.items; |
| 7 | 7 | assert(atoms.len > 0); |
| 8 | 8 | |
| 9 | for (atoms) |atom_index| { | |
| 10 | elf_file.atom(atom_index).?.value = -1; | |
| 9 | for (atoms) |ref| { | |
| 10 | elf_file.atom(ref).?.value = -1; | |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | 13 | var i: usize = 0; |
| 14 | 14 | while (i < atoms.len) { |
| 15 | 15 | const start = i; |
| 16 | 16 | const start_atom = elf_file.atom(atoms[start]).?; |
| 17 | assert(start_atom.flags.alive); | |
| 17 | assert(start_atom.alive); | |
| 18 | 18 | start_atom.value = try advance(shdr, start_atom.size, start_atom.alignment); |
| 19 | 19 | i += 1; |
| 20 | 20 | |
| 21 | 21 | while (i < atoms.len) : (i += 1) { |
| 22 | const atom_index = atoms[i]; | |
| 23 | const atom = elf_file.atom(atom_index).?; | |
| 24 | assert(atom.flags.alive); | |
| 22 | const atom = elf_file.atom(atoms[i]).?; | |
| 23 | assert(atom.alive); | |
| 25 | 24 | if (@as(i64, @intCast(atom.alignment.forward(shdr.sh_size))) - start_atom.value >= max_distance) |
| 26 | 25 | break; |
| 27 | 26 | atom.value = try advance(shdr, atom.size, atom.alignment); |
| ... | ... | @@ -33,10 +32,10 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void { |
| 33 | 32 | thunk.output_section_index = shndx; |
| 34 | 33 | |
| 35 | 34 | // Scan relocs in the group and create trampolines for any unreachable callsite |
| 36 | for (atoms[start..i]) |atom_index| { | |
| 37 | const atom = elf_file.atom(atom_index).?; | |
| 35 | for (atoms[start..i]) |ref| { | |
| 36 | const atom = elf_file.atom(ref).?; | |
| 38 | 37 | const file = atom.file(elf_file).?; |
| 39 | log.debug("atom({d}) {s}", .{ atom_index, atom.name(elf_file) }); | |
| 38 | log.debug("atom({}) {s}", .{ ref, atom.name(elf_file) }); | |
| 40 | 39 | for (atom.relocs(elf_file)) |rel| { |
| 41 | 40 | const is_reachable = switch (cpu_arch) { |
| 42 | 41 | .aarch64 => aarch64.isReachable(atom, rel, elf_file), |
| ... | ... | @@ -51,8 +50,7 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void { |
| 51 | 50 | }; |
| 52 | 51 | try thunk.symbols.put(gpa, target, {}); |
| 53 | 52 | } |
| 54 | try atom.addExtra(.{ .thunk = thunk_index }, elf_file); | |
| 55 | atom.flags.thunk = true; | |
| 53 | atom.addExtra(.{ .thunk = thunk_index }, elf_file); | |
| 56 | 54 | } |
| 57 | 55 | |
| 58 | 56 | thunk.value = try advance(shdr, thunk.size(elf_file), Atom.Alignment.fromNonzeroByteUnits(2)); |
src/link/MachO/InternalObject.zig+1-2| ... | ... | @@ -45,8 +45,7 @@ pub fn deinit(self: *InternalObject, allocator: Allocator) void { |
| 45 | 45 | |
| 46 | 46 | pub fn init(self: *InternalObject, allocator: Allocator) !void { |
| 47 | 47 | // Atom at index 0 is reserved as null atom. |
| 48 | try self.atoms.append(allocator, .{}); | |
| 49 | try self.atoms_extra.append(allocator, 0); | |
| 48 | try self.atoms.append(allocator, .{ .extra = try self.addAtomExtra(allocator, .{}) }); | |
| 50 | 49 | // Null byte in strtab |
| 51 | 50 | try self.strtab.append(allocator, 0); |
| 52 | 51 | } |
src/link/MachO/ZigObject.zig+1-1| ... | ... | @@ -1634,7 +1634,7 @@ fn isThreadlocal(macho_file: *MachO, decl_index: InternPool.DeclIndex) bool { |
| 1634 | 1634 | |
| 1635 | 1635 | fn addAtom(self: *ZigObject, allocator: Allocator) !Atom.Index { |
| 1636 | 1636 | try self.atoms.ensureUnusedCapacity(allocator, 1); |
| 1637 | try self.atoms_extra.ensureUnusedCapacity(allocator, 1); | |
| 1637 | try self.atoms_extra.ensureUnusedCapacity(allocator, @sizeOf(Atom.Extra)); | |
| 1638 | 1638 | return self.addAtomAssumeCapacity(); |
| 1639 | 1639 | } |
| 1640 | 1640 |
test/link/elf.zig+104| ... | ... | @@ -59,6 +59,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { |
| 59 | 59 | // Exercise linker with LLVM backend |
| 60 | 60 | // musl tests |
| 61 | 61 | elf_step.dependOn(testAbsSymbols(b, .{ .target = musl_target })); |
| 62 | elf_step.dependOn(testComdatElimination(b, .{ .target = musl_target })); | |
| 62 | 63 | elf_step.dependOn(testCommonSymbols(b, .{ .target = musl_target })); |
| 63 | 64 | elf_step.dependOn(testCommonSymbolsInArchive(b, .{ .target = musl_target })); |
| 64 | 65 | elf_step.dependOn(testCommentString(b, .{ .target = musl_target })); |
| ... | ... | @@ -368,6 +369,109 @@ fn testCanonicalPlt(b: *Build, opts: Options) *Step { |
| 368 | 369 | return test_step; |
| 369 | 370 | } |
| 370 | 371 | |
| 372 | fn testComdatElimination(b: *Build, opts: Options) *Step { | |
| 373 | const test_step = addTestStep(b, "comdat-elimination", opts); | |
| 374 | ||
| 375 | const a_o = addObject(b, opts, .{ | |
| 376 | .name = "a", | |
| 377 | .cpp_source_bytes = | |
| 378 | \\#include <stdio.h> | |
| 379 | \\inline void foo() { | |
| 380 | \\ printf("calling foo in a\n"); | |
| 381 | \\} | |
| 382 | \\void hello() { | |
| 383 | \\ foo(); | |
| 384 | \\} | |
| 385 | , | |
| 386 | }); | |
| 387 | a_o.linkLibCpp(); | |
| 388 | ||
| 389 | const main_o = addObject(b, opts, .{ | |
| 390 | .name = "main", | |
| 391 | .cpp_source_bytes = | |
| 392 | \\#include <stdio.h> | |
| 393 | \\inline void foo() { | |
| 394 | \\ printf("calling foo in main\n"); | |
| 395 | \\} | |
| 396 | \\void hello(); | |
| 397 | \\int main() { | |
| 398 | \\ foo(); | |
| 399 | \\ hello(); | |
| 400 | \\ return 0; | |
| 401 | \\} | |
| 402 | , | |
| 403 | }); | |
| 404 | main_o.linkLibCpp(); | |
| 405 | ||
| 406 | { | |
| 407 | const exe = addExecutable(b, opts, .{ .name = "main1" }); | |
| 408 | exe.addObject(a_o); | |
| 409 | exe.addObject(main_o); | |
| 410 | exe.linkLibCpp(); | |
| 411 | ||
| 412 | const run = addRunArtifact(exe); | |
| 413 | run.expectStdOutEqual( | |
| 414 | \\calling foo in a | |
| 415 | \\calling foo in a | |
| 416 | \\ | |
| 417 | ); | |
| 418 | test_step.dependOn(&run.step); | |
| 419 | } | |
| 420 | ||
| 421 | { | |
| 422 | const exe = addExecutable(b, opts, .{ .name = "main2" }); | |
| 423 | exe.addObject(main_o); | |
| 424 | exe.addObject(a_o); | |
| 425 | exe.linkLibCpp(); | |
| 426 | ||
| 427 | const run = addRunArtifact(exe); | |
| 428 | run.expectStdOutEqual( | |
| 429 | \\calling foo in main | |
| 430 | \\calling foo in main | |
| 431 | \\ | |
| 432 | ); | |
| 433 | test_step.dependOn(&run.step); | |
| 434 | } | |
| 435 | ||
| 436 | { | |
| 437 | const c_o = addObject(b, opts, .{ .name = "c" }); | |
| 438 | c_o.addObject(main_o); | |
| 439 | c_o.addObject(a_o); | |
| 440 | ||
| 441 | const exe = addExecutable(b, opts, .{ .name = "main3" }); | |
| 442 | exe.addObject(c_o); | |
| 443 | exe.linkLibCpp(); | |
| 444 | ||
| 445 | const run = addRunArtifact(exe); | |
| 446 | run.expectStdOutEqual( | |
| 447 | \\calling foo in main | |
| 448 | \\calling foo in main | |
| 449 | \\ | |
| 450 | ); | |
| 451 | test_step.dependOn(&run.step); | |
| 452 | } | |
| 453 | ||
| 454 | { | |
| 455 | const d_o = addObject(b, opts, .{ .name = "d" }); | |
| 456 | d_o.addObject(a_o); | |
| 457 | d_o.addObject(main_o); | |
| 458 | ||
| 459 | const exe = addExecutable(b, opts, .{ .name = "main4" }); | |
| 460 | exe.addObject(d_o); | |
| 461 | exe.linkLibCpp(); | |
| 462 | ||
| 463 | const run = addRunArtifact(exe); | |
| 464 | run.expectStdOutEqual( | |
| 465 | \\calling foo in a | |
| 466 | \\calling foo in a | |
| 467 | \\ | |
| 468 | ); | |
| 469 | test_step.dependOn(&run.step); | |
| 470 | } | |
| 471 | ||
| 472 | return test_step; | |
| 473 | } | |
| 474 | ||
| 371 | 475 | fn testCommentString(b: *Build, opts: Options) *Step { |
| 372 | 476 | const test_step = addTestStep(b, "comment-string", opts); |
| 373 | 477 |