| ... | @@ -393,7 +393,8 @@ pub fn deinit(self: *Elf) void { | ... | @@ -393,7 +393,8 @@ pub fn deinit(self: *Elf) void { |
| 393 | self.objects.deinit(gpa); | 393 | self.objects.deinit(gpa); |
| 394 | self.shared_objects.deinit(gpa); | 394 | self.shared_objects.deinit(gpa); |
| 395 | | 395 | |
| 396 | for (self.sections.items(.atom_list), self.sections.items(.free_list)) |*atoms, *free_list| { | 396 | for (self.sections.items(.atom_list_2), self.sections.items(.atom_list), self.sections.items(.free_list)) |*atom_list, *atoms, *free_list| { |
| | 397 | atom_list.deinit(gpa); |
| 397 | atoms.deinit(gpa); | 398 | atoms.deinit(gpa); |
| 398 | free_list.deinit(gpa); | 399 | free_list.deinit(gpa); |
| 399 | } | 400 | } |
| ... | @@ -3204,8 +3205,9 @@ fn sortInitFini(self: *Elf) !void { | ... | @@ -3204,8 +3205,9 @@ fn sortInitFini(self: *Elf) !void { |
| 3204 | } | 3205 | } |
| 3205 | }; | 3206 | }; |
| 3206 | | 3207 | |
| 3207 | for (slice.items(.shdr), slice.items(.atom_list)) |shdr, *atom_list| { | 3208 | for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, *atom_list| { |
| 3208 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; | 3209 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; |
| | 3210 | if (atom_list.atoms.items.len == 0) continue; |
| 3209 | | 3211 | |
| 3210 | var is_init_fini = false; | 3212 | var is_init_fini = false; |
| 3211 | var is_ctor_dtor = false; | 3213 | var is_ctor_dtor = false; |
| ... | @@ -3219,15 +3221,13 @@ fn sortInitFini(self: *Elf) !void { | ... | @@ -3219,15 +3221,13 @@ fn sortInitFini(self: *Elf) !void { |
| 3219 | is_ctor_dtor = mem.indexOf(u8, name, ".ctors") != null or mem.indexOf(u8, name, ".dtors") != null; | 3221 | is_ctor_dtor = mem.indexOf(u8, name, ".ctors") != null or mem.indexOf(u8, name, ".dtors") != null; |
| 3220 | }, | 3222 | }, |
| 3221 | } | 3223 | } |
| 3222 | | | |
| 3223 | if (!is_init_fini and !is_ctor_dtor) continue; | 3224 | if (!is_init_fini and !is_ctor_dtor) continue; |
| 3224 | if (atom_list.items.len == 0) continue; | | |
| 3225 | | 3225 | |
| 3226 | var entries = std.ArrayList(Entry).init(gpa); | 3226 | var entries = std.ArrayList(Entry).init(gpa); |
| 3227 | try entries.ensureTotalCapacityPrecise(atom_list.items.len); | 3227 | try entries.ensureTotalCapacityPrecise(atom_list.atoms.items.len); |
| 3228 | defer entries.deinit(); | 3228 | defer entries.deinit(); |
| 3229 | | 3229 | |
| 3230 | for (atom_list.items) |ref| { | 3230 | for (atom_list.atoms.items) |ref| { |
| 3231 | const atom_ptr = self.atom(ref).?; | 3231 | const atom_ptr = self.atom(ref).?; |
| 3232 | const object = atom_ptr.file(self).?.object; | 3232 | const object = atom_ptr.file(self).?.object; |
| 3233 | const priority = blk: { | 3233 | const priority = blk: { |
| ... | @@ -3246,9 +3246,9 @@ fn sortInitFini(self: *Elf) !void { | ... | @@ -3246,9 +3246,9 @@ fn sortInitFini(self: *Elf) !void { |
| 3246 | | 3246 | |
| 3247 | mem.sort(Entry, entries.items, self, Entry.lessThan); | 3247 | mem.sort(Entry, entries.items, self, Entry.lessThan); |
| 3248 | | 3248 | |
| 3249 | atom_list.clearRetainingCapacity(); | 3249 | atom_list.atoms.clearRetainingCapacity(); |
| 3250 | for (entries.items) |entry| { | 3250 | for (entries.items) |entry| { |
| 3251 | atom_list.appendAssumeCapacity(entry.atom_ref); | 3251 | atom_list.atoms.appendAssumeCapacity(entry.atom_ref); |
| 3252 | } | 3252 | } |
| 3253 | } | 3253 | } |
| 3254 | } | 3254 | } |
| ... | @@ -3491,13 +3491,19 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { | ... | @@ -3491,13 +3491,19 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { |
| 3491 | msec.output_section_index = backlinks[msec.output_section_index]; | 3491 | msec.output_section_index = backlinks[msec.output_section_index]; |
| 3492 | } | 3492 | } |
| 3493 | | 3493 | |
| 3494 | for (self.sections.items(.shdr)) |*shdr| { | 3494 | const slice = self.sections.slice(); |
| 3495 | if (shdr.sh_type != elf.SHT_RELA) continue; | 3495 | for (slice.items(.shdr), slice.items(.atom_list_2)) |*shdr, *atom_list| { |
| 3496 | // FIXME:JK we should spin up .symtab potentially earlier, or set all non-dynamic RELA sections | 3496 | atom_list.output_section_index = backlinks[atom_list.output_section_index]; |
| 3497 | // to point at symtab | 3497 | for (atom_list.atoms.items) |ref| { |
| 3498 | // shdr.sh_link = backlinks[shdr.sh_link]; | 3498 | self.atom(ref).?.output_section_index = atom_list.output_section_index; |
| 3499 | shdr.sh_link = self.symtab_section_index.?; | 3499 | } |
| 3500 | shdr.sh_info = backlinks[shdr.sh_info]; | 3500 | if (shdr.sh_type == elf.SHT_RELA) { |
| | 3501 | // FIXME:JK we should spin up .symtab potentially earlier, or set all non-dynamic RELA sections |
| | 3502 | // to point at symtab |
| | 3503 | // shdr.sh_link = backlinks[shdr.sh_link]; |
| | 3504 | shdr.sh_link = self.symtab_section_index.?; |
| | 3505 | shdr.sh_info = backlinks[shdr.sh_info]; |
| | 3506 | } |
| 3501 | } | 3507 | } |
| 3502 | | 3508 | |
| 3503 | if (self.zigObjectPtr()) |zo| { | 3509 | if (self.zigObjectPtr()) |zo| { |
| ... | @@ -3507,79 +3513,71 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { | ... | @@ -3507,79 +3513,71 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { |
| 3507 | } | 3513 | } |
| 3508 | } | 3514 | } |
| 3509 | | 3515 | |
| 3510 | for (self.objects.items) |index| { | | |
| 3511 | const object = self.file(index).?.object; | | |
| 3512 | for (object.section_chunks.items) |*chunk| { | | |
| 3513 | chunk.output_section_index = backlinks[chunk.output_section_index]; | | |
| 3514 | for (chunk.atoms.items) |atom_index| { | | |
| 3515 | object.atom(atom_index).?.output_section_index = chunk.output_section_index; | | |
| 3516 | } | | |
| 3517 | } | | |
| 3518 | } | | |
| 3519 | | | |
| 3520 | for (self.comdat_group_sections.items) |*cg| { | 3516 | for (self.comdat_group_sections.items) |*cg| { |
| 3521 | cg.shndx = backlinks[cg.shndx]; | 3517 | cg.shndx = backlinks[cg.shndx]; |
| 3522 | } | 3518 | } |
| 3523 | | 3519 | |
| 3524 | if (self.symtab_section_index) |index| { | 3520 | if (self.symtab_section_index) |index| { |
| 3525 | const shdr = &self.sections.items(.shdr)[index]; | 3521 | const shdr = &slice.items(.shdr)[index]; |
| 3526 | shdr.sh_link = self.strtab_section_index.?; | 3522 | shdr.sh_link = self.strtab_section_index.?; |
| 3527 | } | 3523 | } |
| 3528 | | 3524 | |
| 3529 | if (self.dynamic_section_index) |index| { | 3525 | if (self.dynamic_section_index) |index| { |
| 3530 | const shdr = &self.sections.items(.shdr)[index]; | 3526 | const shdr = &slice.items(.shdr)[index]; |
| 3531 | shdr.sh_link = self.dynstrtab_section_index.?; | 3527 | shdr.sh_link = self.dynstrtab_section_index.?; |
| 3532 | } | 3528 | } |
| 3533 | | 3529 | |
| 3534 | if (self.dynsymtab_section_index) |index| { | 3530 | if (self.dynsymtab_section_index) |index| { |
| 3535 | const shdr = &self.sections.items(.shdr)[index]; | 3531 | const shdr = &slice.items(.shdr)[index]; |
| 3536 | shdr.sh_link = self.dynstrtab_section_index.?; | 3532 | shdr.sh_link = self.dynstrtab_section_index.?; |
| 3537 | } | 3533 | } |
| 3538 | | 3534 | |
| 3539 | if (self.hash_section_index) |index| { | 3535 | if (self.hash_section_index) |index| { |
| 3540 | const shdr = &self.sections.items(.shdr)[index]; | 3536 | const shdr = &slice.items(.shdr)[index]; |
| 3541 | shdr.sh_link = self.dynsymtab_section_index.?; | 3537 | shdr.sh_link = self.dynsymtab_section_index.?; |
| 3542 | } | 3538 | } |
| 3543 | | 3539 | |
| 3544 | if (self.gnu_hash_section_index) |index| { | 3540 | if (self.gnu_hash_section_index) |index| { |
| 3545 | const shdr = &self.sections.items(.shdr)[index]; | 3541 | const shdr = &slice.items(.shdr)[index]; |
| 3546 | shdr.sh_link = self.dynsymtab_section_index.?; | 3542 | shdr.sh_link = self.dynsymtab_section_index.?; |
| 3547 | } | 3543 | } |
| 3548 | | 3544 | |
| 3549 | if (self.versym_section_index) |index| { | 3545 | if (self.versym_section_index) |index| { |
| 3550 | const shdr = &self.sections.items(.shdr)[index]; | 3546 | const shdr = &slice.items(.shdr)[index]; |
| 3551 | shdr.sh_link = self.dynsymtab_section_index.?; | 3547 | shdr.sh_link = self.dynsymtab_section_index.?; |
| 3552 | } | 3548 | } |
| 3553 | | 3549 | |
| 3554 | if (self.verneed_section_index) |index| { | 3550 | if (self.verneed_section_index) |index| { |
| 3555 | const shdr = &self.sections.items(.shdr)[index]; | 3551 | const shdr = &slice.items(.shdr)[index]; |
| 3556 | shdr.sh_link = self.dynstrtab_section_index.?; | 3552 | shdr.sh_link = self.dynstrtab_section_index.?; |
| 3557 | } | 3553 | } |
| 3558 | | 3554 | |
| 3559 | if (self.rela_dyn_section_index) |index| { | 3555 | if (self.rela_dyn_section_index) |index| { |
| 3560 | const shdr = &self.sections.items(.shdr)[index]; | 3556 | const shdr = &slice.items(.shdr)[index]; |
| 3561 | shdr.sh_link = self.dynsymtab_section_index orelse 0; | 3557 | shdr.sh_link = self.dynsymtab_section_index orelse 0; |
| 3562 | } | 3558 | } |
| 3563 | | 3559 | |
| 3564 | if (self.rela_plt_section_index) |index| { | 3560 | if (self.rela_plt_section_index) |index| { |
| 3565 | const shdr = &self.sections.items(.shdr)[index]; | 3561 | const shdr = &slice.items(.shdr)[index]; |
| 3566 | shdr.sh_link = self.dynsymtab_section_index.?; | 3562 | shdr.sh_link = self.dynsymtab_section_index.?; |
| 3567 | shdr.sh_info = self.plt_section_index.?; | 3563 | shdr.sh_info = self.plt_section_index.?; |
| 3568 | } | 3564 | } |
| 3569 | | 3565 | |
| 3570 | if (self.eh_frame_rela_section_index) |index| { | 3566 | if (self.eh_frame_rela_section_index) |index| { |
| 3571 | const shdr = &self.sections.items(.shdr)[index]; | 3567 | const shdr = &slice.items(.shdr)[index]; |
| 3572 | shdr.sh_link = self.symtab_section_index.?; | 3568 | shdr.sh_link = self.symtab_section_index.?; |
| 3573 | shdr.sh_info = self.eh_frame_section_index.?; | 3569 | shdr.sh_info = self.eh_frame_section_index.?; |
| 3574 | } | 3570 | } |
| 3575 | } | 3571 | } |
| 3576 | | 3572 | |
| 3577 | fn updateSectionSizes(self: *Elf) !void { | 3573 | fn updateSectionSizes(self: *Elf) !void { |
| 3578 | for (self.objects.items) |index| { | 3574 | const slice = self.sections.slice(); |
| 3579 | try self.file(index).?.object.allocateAtoms(self); | 3575 | for (slice.items(.atom_list_2)) |*atom_list| { |
| | 3576 | if (atom_list.atoms.items.len == 0) continue; |
| | 3577 | atom_list.updateSize(self); |
| | 3578 | try atom_list.allocate(self); |
| 3580 | } | 3579 | } |
| 3581 | | 3580 | |
| 3582 | const slice = self.sections.slice(); | | |
| 3583 | if (self.requiresThunks()) { | 3581 | if (self.requiresThunks()) { |
| 3584 | for (slice.items(.shdr), slice.items(.atom_list), 0..) |*shdr, atom_list, shndx| { | 3582 | for (slice.items(.shdr), slice.items(.atom_list), 0..) |*shdr, atom_list, shndx| { |
| 3585 | if (shdr.sh_flags & elf.SHF_EXECINSTR == 0) continue; | 3583 | if (shdr.sh_flags & elf.SHF_EXECINSTR == 0) continue; |
| ... | @@ -4033,15 +4031,38 @@ fn allocateSpecialPhdrs(self: *Elf) void { | ... | @@ -4033,15 +4031,38 @@ fn allocateSpecialPhdrs(self: *Elf) void { |
| 4033 | } | 4031 | } |
| 4034 | | 4032 | |
| 4035 | fn writeAtoms(self: *Elf) !void { | 4033 | fn writeAtoms(self: *Elf) !void { |
| 4036 | for (self.objects.items) |index| { | 4034 | const gpa = self.base.comp.gpa; |
| 4037 | try self.file(index).?.object.writeAtoms(self); | 4035 | |
| | 4036 | var undefs = std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(Ref)).init(gpa); |
| | 4037 | defer { |
| | 4038 | for (undefs.values()) |*refs| { |
| | 4039 | refs.deinit(); |
| | 4040 | } |
| | 4041 | undefs.deinit(); |
| 4038 | } | 4042 | } |
| 4039 | | 4043 | |
| 4040 | if (self.requiresThunks()) { | 4044 | var buffer = std.ArrayList(u8).init(gpa); |
| 4041 | const gpa = self.base.comp.gpa; | 4045 | defer buffer.deinit(); |
| 4042 | var buffer = std.ArrayList(u8).init(gpa); | 4046 | |
| 4043 | defer buffer.deinit(); | 4047 | const slice = self.sections.slice(); |
| | 4048 | var has_reloc_errors = false; |
| | 4049 | for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, atom_list| { |
| | 4050 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| | 4051 | if (atom_list.atoms.items.len == 0) continue; |
| | 4052 | atom_list.write(&buffer, &undefs, self) catch |err| switch (err) { |
| | 4053 | error.UnsupportedCpuArch => { |
| | 4054 | try self.reportUnsupportedCpuArch(); |
| | 4055 | return error.FlushFailure; |
| | 4056 | }, |
| | 4057 | error.RelocFailure, error.RelaxFailure => has_reloc_errors = true, |
| | 4058 | else => |e| return e, |
| | 4059 | }; |
| | 4060 | } |
| | 4061 | |
| | 4062 | try self.reportUndefinedSymbols(&undefs); |
| | 4063 | if (has_reloc_errors) return error.FlushFailure; |
| 4044 | | 4064 | |
| | 4065 | if (self.requiresThunks()) { |
| 4045 | for (self.thunks.items) |th| { | 4066 | for (self.thunks.items) |th| { |
| 4046 | const thunk_size = th.size(self); | 4067 | const thunk_size = th.size(self); |
| 4047 | try buffer.ensureUnusedCapacity(thunk_size); | 4068 | try buffer.ensureUnusedCapacity(thunk_size); |
| ... | @@ -4993,7 +5014,7 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 { | ... | @@ -4993,7 +5014,7 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 { |
| 4993 | return off; | 5014 | return off; |
| 4994 | } | 5015 | } |
| 4995 | | 5016 | |
| 4996 | pub fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void { | 5017 | fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void { |
| 4997 | const gpa = self.base.comp.gpa; | 5018 | const gpa = self.base.comp.gpa; |
| 4998 | const max_notes = 4; | 5019 | const max_notes = 4; |
| 4999 | | 5020 | |
| ... | @@ -5061,7 +5082,7 @@ fn reportMissingLibraryError( | ... | @@ -5061,7 +5082,7 @@ fn reportMissingLibraryError( |
| 5061 | } | 5082 | } |
| 5062 | } | 5083 | } |
| 5063 | | 5084 | |
| 5064 | pub fn reportUnsupportedCpuArch(self: *Elf) error{OutOfMemory}!void { | 5085 | fn reportUnsupportedCpuArch(self: *Elf) error{OutOfMemory}!void { |
| 5065 | var err = try self.base.addErrorWithNotes(0); | 5086 | var err = try self.base.addErrorWithNotes(0); |
| 5066 | try err.addMsg("fatal linker error: unsupported CPU architecture {s}", .{ | 5087 | try err.addMsg("fatal linker error: unsupported CPU architecture {s}", .{ |
| 5067 | @tagName(self.getTarget().cpu.arch), | 5088 | @tagName(self.getTarget().cpu.arch), |
| ... | @@ -5248,9 +5269,8 @@ fn fmtDumpState( | ... | @@ -5248,9 +5269,8 @@ fn fmtDumpState( |
| 5248 | try writer.print("object({d}) : {}", .{ index, object.fmtPath() }); | 5269 | try writer.print("object({d}) : {}", .{ index, object.fmtPath() }); |
| 5249 | if (!object.alive) try writer.writeAll(" : [*]"); | 5270 | if (!object.alive) try writer.writeAll(" : [*]"); |
| 5250 | try writer.writeByte('\n'); | 5271 | try writer.writeByte('\n'); |
| 5251 | try writer.print("{}{}{}{}{}{}\n", .{ | 5272 | try writer.print("{}{}{}{}{}\n", .{ |
| 5252 | object.fmtAtoms(self), | 5273 | object.fmtAtoms(self), |
| 5253 | object.fmtSectionChunks(self), | | |
| 5254 | object.fmtCies(self), | 5274 | object.fmtCies(self), |
| 5255 | object.fmtFdes(self), | 5275 | object.fmtFdes(self), |
| 5256 | object.fmtSymtab(self), | 5276 | object.fmtSymtab(self), |
| ... | @@ -5274,6 +5294,14 @@ fn fmtDumpState( | ... | @@ -5274,6 +5294,14 @@ fn fmtDumpState( |
| 5274 | try writer.print("{}\n", .{linker_defined.fmtSymtab(self)}); | 5294 | try writer.print("{}\n", .{linker_defined.fmtSymtab(self)}); |
| 5275 | } | 5295 | } |
| 5276 | | 5296 | |
| | 5297 | const slice = self.sections.slice(); |
| | 5298 | { |
| | 5299 | try writer.writeAll("atom lists\n"); |
| | 5300 | for (slice.items(.shdr), slice.items(.atom_list_2), 0..) |shdr, atom_list, shndx| { |
| | 5301 | try writer.print("shdr({d}) : {s} : {}", .{ shndx, self.getShString(shdr.sh_name), atom_list.fmt(self) }); |
| | 5302 | } |
| | 5303 | } |
| | 5304 | |
| 5277 | if (self.requiresThunks()) { | 5305 | if (self.requiresThunks()) { |
| 5278 | try writer.writeAll("thunks\n"); | 5306 | try writer.writeAll("thunks\n"); |
| 5279 | for (self.thunks.items, 0..) |th, index| { | 5307 | for (self.thunks.items, 0..) |th, index| { |
| ... | @@ -5295,7 +5323,7 @@ fn fmtDumpState( | ... | @@ -5295,7 +5323,7 @@ fn fmtDumpState( |
| 5295 | } | 5323 | } |
| 5296 | | 5324 | |
| 5297 | try writer.writeAll("\nOutput shdrs\n"); | 5325 | try writer.writeAll("\nOutput shdrs\n"); |
| 5298 | for (self.sections.items(.shdr), self.sections.items(.phndx), 0..) |shdr, phndx, shndx| { | 5326 | for (slice.items(.shdr), slice.items(.phndx), 0..) |shdr, phndx, shndx| { |
| 5299 | try writer.print(" shdr({d}) : phdr({?d}) : {}\n", .{ | 5327 | try writer.print(" shdr({d}) : phdr({?d}) : {}\n", .{ |
| 5300 | shndx, | 5328 | shndx, |
| 5301 | phndx, | 5329 | phndx, |
| ... | @@ -5549,8 +5577,14 @@ const Section = struct { | ... | @@ -5549,8 +5577,14 @@ const Section = struct { |
| 5549 | phndx: ?u32 = null, | 5577 | phndx: ?u32 = null, |
| 5550 | | 5578 | |
| 5551 | /// List of atoms contributing to this section. | 5579 | /// List of atoms contributing to this section. |
| | 5580 | /// TODO currently this is only used for relocations tracking in relocatable mode |
| | 5581 | /// but will be merged with atom_list_2. |
| 5552 | atom_list: std.ArrayListUnmanaged(Ref) = .{}, | 5582 | atom_list: std.ArrayListUnmanaged(Ref) = .{}, |
| 5553 | | 5583 | |
| | 5584 | /// List of atoms contributing to this section. |
| | 5585 | /// This can be used by sections that require special handling such as init/fini array, etc. |
| | 5586 | atom_list_2: AtomList = .{}, |
| | 5587 | |
| 5554 | /// Index of the last allocated atom in this section. | 5588 | /// Index of the last allocated atom in this section. |
| 5555 | last_atom: Ref = .{ .index = 0, .file = 0 }, | 5589 | last_atom: Ref = .{ .index = 0, .file = 0 }, |
| 5556 | | 5590 | |
| ... | @@ -5690,6 +5724,7 @@ const Air = @import("../Air.zig"); | ... | @@ -5690,6 +5724,7 @@ const Air = @import("../Air.zig"); |
| 5690 | const Allocator = std.mem.Allocator; | 5724 | const Allocator = std.mem.Allocator; |
| 5691 | const Archive = @import("Elf/Archive.zig"); | 5725 | const Archive = @import("Elf/Archive.zig"); |
| 5692 | pub const Atom = @import("Elf/Atom.zig"); | 5726 | pub const Atom = @import("Elf/Atom.zig"); |
| | 5727 | const AtomList = @import("Elf/AtomList.zig"); |
| 5693 | const Cache = std.Build.Cache; | 5728 | const Cache = std.Build.Cache; |
| 5694 | const Path = Cache.Path; | 5729 | const Path = Cache.Path; |
| 5695 | const Compilation = @import("../Compilation.zig"); | 5730 | const Compilation = @import("../Compilation.zig"); |