| author | |
| committer | |
| log | 9ccd94d56037e05e87755887e334aa6a1a096ec5 |
| tree | 9abe67a02442a5b6bad0a653104a98088e95ccd4 |
| parent | 53340544c6666d9d35463f509fbe0416f607c91c |
5 files changed, 167 insertions(+), 72 deletions(-)
src/link/Elf.zig+49-5| ... | ... | @@ -1235,7 +1235,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1235 | 1235 | // input Object files. |
| 1236 | 1236 | // Any qualifing unresolved symbol will be upgraded to an absolute, weak |
| 1237 | 1237 | // symbol for potential resolution at load-time. |
| 1238 | try self.resolveSymbols(); | |
| 1238 | self.resolveSymbols(); | |
| 1239 | self.markEhFrameAtomsDead(); | |
| 1239 | 1240 | self.markImportsExports(); |
| 1240 | 1241 | self.claimUnresolved(); |
| 1241 | 1242 | |
| ... | ... | @@ -1610,7 +1611,7 @@ fn parseArchive( |
| 1610 | 1611 | /// 4. Reset state of all resolved globals since we will redo this bit on the pruned set. |
| 1611 | 1612 | /// 5. Remove references to dead objects/shared objects |
| 1612 | 1613 | /// 6. Re-run symbol resolution on pruned objects and shared objects sets. |
| 1613 | fn resolveSymbols(self: *Elf) error{Overflow}!void { | |
| 1614 | fn resolveSymbols(self: *Elf) void { | |
| 1614 | 1615 | // Resolve symbols in the ZigModule. For now, we assume that it's always live. |
| 1615 | 1616 | if (self.zig_module_index) |index| self.file(index).?.resolveSymbols(self); |
| 1616 | 1617 | // Resolve symbols on the set of all objects and shared objects (even if some are unneeded). |
| ... | ... | @@ -1652,11 +1653,11 @@ fn resolveSymbols(self: *Elf) error{Overflow}!void { |
| 1652 | 1653 | const cg = self.comdatGroup(cg_index); |
| 1653 | 1654 | const cg_owner = self.comdatGroupOwner(cg.owner); |
| 1654 | 1655 | if (cg_owner.file != index) { |
| 1655 | for (try object.comdatGroupMembers(cg.shndx)) |shndx| { | |
| 1656 | for (object.comdatGroupMembers(cg.shndx)) |shndx| { | |
| 1656 | 1657 | const atom_index = object.atoms.items[shndx]; |
| 1657 | 1658 | if (self.atom(atom_index)) |atom_ptr| { |
| 1658 | 1659 | atom_ptr.flags.alive = false; |
| 1659 | // atom_ptr.markFdesDead(self); | |
| 1660 | atom_ptr.markFdesDead(self); | |
| 1660 | 1661 | } |
| 1661 | 1662 | } |
| 1662 | 1663 | } |
| ... | ... | @@ -1680,6 +1681,14 @@ fn markLive(self: *Elf) void { |
| 1680 | 1681 | } |
| 1681 | 1682 | } |
| 1682 | 1683 | |
| 1684 | fn markEhFrameAtomsDead(self: *Elf) void { | |
| 1685 | for (self.objects.items) |index| { | |
| 1686 | const file_ptr = self.file(index).?; | |
| 1687 | if (!file_ptr.isAlive()) continue; | |
| 1688 | file_ptr.object.markEhFrameAtomsDead(self); | |
| 1689 | } | |
| 1690 | } | |
| 1691 | ||
| 1683 | 1692 | fn markImportsExports(self: *Elf) void { |
| 1684 | 1693 | const mark = struct { |
| 1685 | 1694 | fn mark(elf_file: *Elf, file_index: File.Index) void { |
| ... | ... | @@ -3389,17 +3398,39 @@ fn initSections(self: *Elf) !void { |
| 3389 | 3398 | .p32 => true, |
| 3390 | 3399 | .p64 => false, |
| 3391 | 3400 | }; |
| 3401 | const ptr_size = self.ptrWidthBytes(); | |
| 3392 | 3402 | |
| 3393 | 3403 | for (self.objects.items) |index| { |
| 3394 | 3404 | try self.file(index).?.object.initOutputSections(self); |
| 3395 | 3405 | } |
| 3396 | 3406 | |
| 3407 | const needs_eh_frame = for (self.objects.items) |index| { | |
| 3408 | if (self.file(index).?.object.cies.items.len > 0) break true; | |
| 3409 | } else false; | |
| 3410 | if (needs_eh_frame) { | |
| 3411 | self.eh_frame_section_index = try self.addSection(.{ | |
| 3412 | .name = ".eh_frame", | |
| 3413 | .type = elf.SHT_PROGBITS, | |
| 3414 | .flags = elf.SHF_ALLOC, | |
| 3415 | .addralign = ptr_size, | |
| 3416 | }); | |
| 3417 | ||
| 3418 | if (self.base.options.eh_frame_hdr) { | |
| 3419 | self.eh_frame_hdr_section_index = try self.addSection(.{ | |
| 3420 | .name = ".eh_frame_hdr", | |
| 3421 | .type = elf.SHT_PROGBITS, | |
| 3422 | .flags = elf.SHF_ALLOC, | |
| 3423 | .addralign = ptr_size, | |
| 3424 | }); | |
| 3425 | } | |
| 3426 | } | |
| 3427 | ||
| 3397 | 3428 | if (self.got.entries.items.len > 0 and self.got_section_index == null) { |
| 3398 | 3429 | self.got_section_index = try self.addSection(.{ |
| 3399 | 3430 | .name = ".got", |
| 3400 | 3431 | .type = elf.SHT_PROGBITS, |
| 3401 | 3432 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| 3402 | .addralign = self.ptrWidthBytes(), | |
| 3433 | .addralign = ptr_size, | |
| 3403 | 3434 | }); |
| 3404 | 3435 | } |
| 3405 | 3436 | |
| ... | ... | @@ -3533,6 +3564,18 @@ fn updateSectionSizes(self: *Elf) !void { |
| 3533 | 3564 | self.file(index).?.object.updateSectionSizes(self); |
| 3534 | 3565 | } |
| 3535 | 3566 | |
| 3567 | if (self.eh_frame_section_index) |index| { | |
| 3568 | const shdr = &self.shdrs.items[index]; | |
| 3569 | shdr.sh_size = try eh_frame.calcEhFrameSize(self); | |
| 3570 | shdr.sh_addralign = @alignOf(u64); | |
| 3571 | } | |
| 3572 | ||
| 3573 | if (self.eh_frame_hdr_section_index) |index| { | |
| 3574 | const shdr = &self.shdrs.items[index]; | |
| 3575 | shdr.sh_size = eh_frame.calcEhFrameHdrSize(self); | |
| 3576 | shdr.sh_addralign = @alignOf(u32); | |
| 3577 | } | |
| 3578 | ||
| 3536 | 3579 | if (self.got_section_index) |index| { |
| 3537 | 3580 | self.shdrs.items[index].sh_size = self.got.size(self); |
| 3538 | 3581 | } |
| ... | ... | @@ -4937,6 +4980,7 @@ const math = std.math; |
| 4937 | 4980 | const mem = std.mem; |
| 4938 | 4981 | |
| 4939 | 4982 | const codegen = @import("../codegen.zig"); |
| 4983 | const eh_frame = @import("Elf/eh_frame.zig"); | |
| 4940 | 4984 | const glibc = @import("../glibc.zig"); |
| 4941 | 4985 | const link = @import("../link.zig"); |
| 4942 | 4986 | const lldMain = @import("../main.zig").lldMain; |
src/link/Elf/Atom.zig+21-6| ... | ... | @@ -49,7 +49,7 @@ pub fn file(self: Atom, elf_file: *Elf) ?File { |
| 49 | 49 | return elf_file.file(self.file_index); |
| 50 | 50 | } |
| 51 | 51 | |
| 52 | pub fn inputShdr(self: Atom, elf_file: *Elf) elf.Elf64_Shdr { | |
| 52 | pub fn inputShdr(self: Atom, elf_file: *Elf) Object.ElfShdr { | |
| 53 | 53 | const object = self.file(elf_file).?.object; |
| 54 | 54 | return object.shdrs.items[self.input_section_index]; |
| 55 | 55 | } |
| ... | ... | @@ -272,7 +272,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void { |
| 272 | 272 | self.* = .{}; |
| 273 | 273 | } |
| 274 | 274 | |
| 275 | pub fn relocs(self: Atom, elf_file: *Elf) error{Overflow}![]align(1) const elf.Elf64_Rela { | |
| 275 | pub fn relocs(self: Atom, elf_file: *Elf) []align(1) const elf.Elf64_Rela { | |
| 276 | 276 | return switch (self.file(elf_file).?) { |
| 277 | 277 | .zig_module => |x| x.relocs.items[self.relocs_section_index].items, |
| 278 | 278 | .object => |x| x.getRelocs(self.relocs_section_index), |
| ... | ... | @@ -280,6 +280,18 @@ pub fn relocs(self: Atom, elf_file: *Elf) error{Overflow}![]align(1) const elf.E |
| 280 | 280 | }; |
| 281 | 281 | } |
| 282 | 282 | |
| 283 | pub fn fdes(self: Atom, elf_file: *Elf) []Fde { | |
| 284 | if (self.fde_start == self.fde_end) return &[0]Fde{}; | |
| 285 | const object = self.file(elf_file).?.object; | |
| 286 | return object.fdes.items[self.fde_start..self.fde_end]; | |
| 287 | } | |
| 288 | ||
| 289 | pub fn markFdesDead(self: Atom, elf_file: *Elf) void { | |
| 290 | for (self.fdes(elf_file)) |*fde| { | |
| 291 | fde.alive = false; | |
| 292 | } | |
| 293 | } | |
| 294 | ||
| 283 | 295 | pub fn addReloc(self: Atom, elf_file: *Elf, reloc: elf.Elf64_Rela) !void { |
| 284 | 296 | const gpa = elf_file.base.allocator; |
| 285 | 297 | const file_ptr = self.file(elf_file).?; |
| ... | ... | @@ -296,8 +308,8 @@ pub fn freeRelocs(self: Atom, elf_file: *Elf) void { |
| 296 | 308 | zig_module.relocs.items[self.relocs_section_index].clearRetainingCapacity(); |
| 297 | 309 | } |
| 298 | 310 | |
| 299 | pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) error{Overflow}!bool { | |
| 300 | for (try self.relocs(elf_file)) |rel| { | |
| 311 | pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) bool { | |
| 312 | for (self.relocs(elf_file)) |rel| { | |
| 301 | 313 | if (rel.r_type() == elf.R_X86_64_GOTTPOFF) return true; |
| 302 | 314 | } |
| 303 | 315 | return false; |
| ... | ... | @@ -306,7 +318,7 @@ pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) error{Overflow}!bool { |
| 306 | 318 | pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype) !void { |
| 307 | 319 | const is_dyn_lib = elf_file.isDynLib(); |
| 308 | 320 | const file_ptr = self.file(elf_file).?; |
| 309 | const rels = try self.relocs(elf_file); | |
| 321 | const rels = self.relocs(elf_file); | |
| 310 | 322 | var i: usize = 0; |
| 311 | 323 | while (i < rels.len) : (i += 1) { |
| 312 | 324 | const rel = rels[i]; |
| ... | ... | @@ -456,7 +468,7 @@ pub fn resolveRelocs(self: Atom, elf_file: *Elf, code: []u8) !void { |
| 456 | 468 | var stream = std.io.fixedBufferStream(code); |
| 457 | 469 | const cwriter = stream.writer(); |
| 458 | 470 | |
| 459 | const rels = try self.relocs(elf_file); | |
| 471 | const rels = self.relocs(elf_file); | |
| 460 | 472 | var i: usize = 0; |
| 461 | 473 | while (i < rels.len) : (i += 1) { |
| 462 | 474 | const rel = rels[i]; |
| ... | ... | @@ -841,11 +853,14 @@ const x86_64 = struct { |
| 841 | 853 | const std = @import("std"); |
| 842 | 854 | const assert = std.debug.assert; |
| 843 | 855 | const elf = std.elf; |
| 856 | const eh_frame = @import("eh_frame.zig"); | |
| 844 | 857 | const log = std.log.scoped(.link); |
| 845 | 858 | const relocs_log = std.log.scoped(.link_relocs); |
| 846 | 859 | |
| 847 | 860 | const Allocator = std.mem.Allocator; |
| 848 | 861 | const Atom = @This(); |
| 849 | 862 | const Elf = @import("../Elf.zig"); |
| 863 | const Fde = eh_frame.Fde; | |
| 850 | 864 | const File = @import("file.zig").File; |
| 865 | const Object = @import("Object.zig"); | |
| 851 | 866 | const Symbol = @import("Symbol.zig"); |
src/link/Elf/Object.zig+72-34| ... | ... | @@ -4,7 +4,7 @@ data: []const u8, |
| 4 | 4 | index: File.Index, |
| 5 | 5 | |
| 6 | 6 | header: ?elf.Elf64_Ehdr = null, |
| 7 | shdrs: std.ArrayListUnmanaged(elf.Elf64_Shdr) = .{}, | |
| 7 | shdrs: std.ArrayListUnmanaged(ElfShdr) = .{}, | |
| 8 | 8 | strings: StringTable(.object_strings) = .{}, |
| 9 | 9 | symtab: []align(1) const elf.Elf64_Sym = &[0]elf.Elf64_Sym{}, |
| 10 | 10 | strtab: []const u8 = &[0]u8{}, |
| ... | ... | @@ -64,8 +64,13 @@ pub fn parse(self: *Object, elf_file: *Elf) !void { |
| 64 | 64 | [*]align(1) const elf.Elf64_Shdr, |
| 65 | 65 | @ptrCast(self.data.ptr + shoff), |
| 66 | 66 | )[0..self.header.?.e_shnum]; |
| 67 | try self.shdrs.appendUnalignedSlice(gpa, shdrs); | |
| 68 | try self.strings.buffer.appendSlice(gpa, try self.shdrContents(self.header.?.e_shstrndx)); | |
| 67 | try self.shdrs.ensureTotalCapacityPrecise(gpa, shdrs.len); | |
| 68 | ||
| 69 | for (shdrs) |shdr| { | |
| 70 | self.shdrs.appendAssumeCapacity(try ElfShdr.fromElf64Shdr(shdr)); | |
| 71 | } | |
| 72 | ||
| 73 | try self.strings.buffer.appendSlice(gpa, self.shdrContents(self.header.?.e_shstrndx)); | |
| 69 | 74 | |
| 70 | 75 | const symtab_index = for (self.shdrs.items, 0..) |shdr, i| switch (shdr.sh_type) { |
| 71 | 76 | elf.SHT_SYMTAB => break @as(u16, @intCast(i)), |
| ... | ... | @@ -76,21 +81,21 @@ pub fn parse(self: *Object, elf_file: *Elf) !void { |
| 76 | 81 | const shdr = shdrs[index]; |
| 77 | 82 | self.first_global = shdr.sh_info; |
| 78 | 83 | |
| 79 | const symtab = try self.shdrContents(index); | |
| 84 | const symtab = self.shdrContents(index); | |
| 80 | 85 | const nsyms = @divExact(symtab.len, @sizeOf(elf.Elf64_Sym)); |
| 81 | 86 | self.symtab = @as([*]align(1) const elf.Elf64_Sym, @ptrCast(symtab.ptr))[0..nsyms]; |
| 82 | self.strtab = try self.shdrContents(@as(u16, @intCast(shdr.sh_link))); | |
| 87 | self.strtab = self.shdrContents(@as(u16, @intCast(shdr.sh_link))); | |
| 83 | 88 | } |
| 84 | 89 | |
| 85 | 90 | try self.initAtoms(elf_file); |
| 86 | 91 | try self.initSymtab(elf_file); |
| 87 | 92 | |
| 88 | // for (self.shdrs.items, 0..) |shdr, i| { | |
| 89 | // const atom = elf_file.atom(self.atoms.items[i]) orelse continue; | |
| 90 | // if (!atom.alive) continue; | |
| 91 | // if (shdr.sh_type == elf.SHT_X86_64_UNWIND or mem.eql(u8, atom.name(elf_file), ".eh_frame")) | |
| 92 | // try self.parseEhFrame(@as(u16, @intCast(i)), elf_file); | |
| 93 | // } | |
| 93 | for (self.shdrs.items, 0..) |shdr, i| { | |
| 94 | const atom = elf_file.atom(self.atoms.items[i]) orelse continue; | |
| 95 | if (!atom.flags.alive) continue; | |
| 96 | if (shdr.sh_type == elf.SHT_X86_64_UNWIND or mem.eql(u8, atom.name(elf_file), ".eh_frame")) | |
| 97 | try self.parseEhFrame(@as(u16, @intCast(i)), elf_file); | |
| 98 | } | |
| 94 | 99 | } |
| 95 | 100 | |
| 96 | 101 | fn initAtoms(self: *Object, elf_file: *Elf) !void { |
| ... | ... | @@ -120,7 +125,7 @@ fn initAtoms(self: *Object, elf_file: *Elf) !void { |
| 120 | 125 | }; |
| 121 | 126 | |
| 122 | 127 | const shndx = @as(u16, @intCast(i)); |
| 123 | const group_raw_data = try self.shdrContents(shndx); | |
| 128 | const group_raw_data = self.shdrContents(shndx); | |
| 124 | 129 | const group_nmembers = @divExact(group_raw_data.len, @sizeOf(u32)); |
| 125 | 130 | const group_members = @as([*]align(1) const u32, @ptrCast(group_raw_data.ptr))[0..group_nmembers]; |
| 126 | 131 | |
| ... | ... | @@ -173,11 +178,11 @@ fn initAtoms(self: *Object, elf_file: *Elf) !void { |
| 173 | 178 | |
| 174 | 179 | fn addAtom( |
| 175 | 180 | self: *Object, |
| 176 | shdr: elf.Elf64_Shdr, | |
| 181 | shdr: ElfShdr, | |
| 177 | 182 | shndx: u16, |
| 178 | 183 | name: [:0]const u8, |
| 179 | 184 | elf_file: *Elf, |
| 180 | ) error{ OutOfMemory, Overflow }!void { | |
| 185 | ) error{OutOfMemory}!void { | |
| 181 | 186 | const atom_index = try elf_file.addAtom(); |
| 182 | 187 | const atom = elf_file.atom(atom_index).?; |
| 183 | 188 | atom.atom_index = atom_index; |
| ... | ... | @@ -188,7 +193,7 @@ fn addAtom( |
| 188 | 193 | self.atoms.items[shndx] = atom_index; |
| 189 | 194 | |
| 190 | 195 | if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) { |
| 191 | const data = try self.shdrContents(shndx); | |
| 196 | const data = self.shdrContents(shndx); | |
| 192 | 197 | const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*; |
| 193 | 198 | atom.size = chdr.ch_size; |
| 194 | 199 | atom.alignment = Alignment.fromNonzeroByteUnits(chdr.ch_addralign); |
| ... | ... | @@ -198,7 +203,7 @@ fn addAtom( |
| 198 | 203 | } |
| 199 | 204 | } |
| 200 | 205 | |
| 201 | fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{OutOfMemory}!u16 { | |
| 206 | fn initOutputSection(self: Object, elf_file: *Elf, shdr: ElfShdr) error{OutOfMemory}!u16 { | |
| 202 | 207 | const name = blk: { |
| 203 | 208 | const name = self.strings.getAssumeExists(shdr.sh_name); |
| 204 | 209 | if (shdr.sh_flags & elf.SHF_MERGE != 0) break :blk name; |
| ... | ... | @@ -244,7 +249,6 @@ fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{O |
| 244 | 249 | } |
| 245 | 250 | |
| 246 | 251 | fn skipShdr(self: *Object, index: u16, elf_file: *Elf) bool { |
| 247 | _ = elf_file; | |
| 248 | 252 | const shdr = self.shdrs.items[index]; |
| 249 | 253 | const name = self.strings.getAssumeExists(shdr.sh_name); |
| 250 | 254 | const ignore = blk: { |
| ... | ... | @@ -252,9 +256,8 @@ fn skipShdr(self: *Object, index: u16, elf_file: *Elf) bool { |
| 252 | 256 | if (mem.startsWith(u8, name, ".comment")) break :blk true; |
| 253 | 257 | if (mem.startsWith(u8, name, ".llvm_addrsig")) break :blk true; |
| 254 | 258 | if (mem.startsWith(u8, name, ".eh_frame")) break :blk true; |
| 255 | // if (elf_file.base.options.strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and | |
| 256 | // mem.startsWith(u8, name, ".debug")) break :blk true; | |
| 257 | if (shdr.sh_flags & elf.SHF_ALLOC == 0 and mem.startsWith(u8, name, ".debug")) break :blk true; | |
| 259 | if (elf_file.base.options.strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and | |
| 260 | mem.startsWith(u8, name, ".debug")) break :blk true; | |
| 258 | 261 | break :blk false; |
| 259 | 262 | }; |
| 260 | 263 | return ignore; |
| ... | ... | @@ -303,8 +306,8 @@ fn parseEhFrame(self: *Object, shndx: u16, elf_file: *Elf) !void { |
| 303 | 306 | }; |
| 304 | 307 | |
| 305 | 308 | const gpa = elf_file.base.allocator; |
| 306 | const raw = try self.shdrContents(shndx); | |
| 307 | const relocs = try self.getRelocs(relocs_shndx); | |
| 309 | const raw = self.shdrContents(shndx); | |
| 310 | const relocs = self.getRelocs(relocs_shndx); | |
| 308 | 311 | const fdes_start = self.fdes.items.len; |
| 309 | 312 | const cies_start = self.cies.items.len; |
| 310 | 313 | |
| ... | ... | @@ -408,7 +411,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void { |
| 408 | 411 | const shdr = atom.inputShdr(elf_file); |
| 409 | 412 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; |
| 410 | 413 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| 411 | if (try atom.scanRelocsRequiresCode(elf_file)) { | |
| 414 | if (atom.scanRelocsRequiresCode(elf_file)) { | |
| 412 | 415 | // TODO ideally, we don't have to decompress at this stage (should already be done) |
| 413 | 416 | // and we just fetch the code slice. |
| 414 | 417 | const code = try self.codeDecompressAlloc(elf_file, atom_index); |
| ... | ... | @@ -418,7 +421,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void { |
| 418 | 421 | } |
| 419 | 422 | |
| 420 | 423 | for (self.cies.items) |cie| { |
| 421 | for (try cie.relocs(elf_file)) |rel| { | |
| 424 | for (cie.relocs(elf_file)) |rel| { | |
| 422 | 425 | const sym = elf_file.symbol(self.symbols.items[rel.r_sym()]); |
| 423 | 426 | if (sym.flags.import) { |
| 424 | 427 | if (sym.type(elf_file) != elf.STT_FUNC) |
| ... | ... | @@ -518,6 +521,15 @@ pub fn markLive(self: *Object, elf_file: *Elf) void { |
| 518 | 521 | } |
| 519 | 522 | } |
| 520 | 523 | |
| 524 | pub fn markEhFrameAtomsDead(self: Object, elf_file: *Elf) void { | |
| 525 | for (self.atoms.items) |atom_index| { | |
| 526 | const atom = elf_file.atom(atom_index) orelse continue; | |
| 527 | const is_eh_frame = atom.inputShdr(elf_file).sh_type == elf.SHT_X86_64_UNWIND or | |
| 528 | mem.eql(u8, atom.name(elf_file), ".eh_frame"); | |
| 529 | if (atom.flags.alive and is_eh_frame) atom.flags.alive = false; | |
| 530 | } | |
| 531 | } | |
| 532 | ||
| 521 | 533 | pub fn checkDuplicates(self: *Object, elf_file: *Elf) void { |
| 522 | 534 | const first_global = self.first_global orelse return; |
| 523 | 535 | for (self.globals(), 0..) |index, i| { |
| ... | ... | @@ -747,12 +759,10 @@ pub fn globals(self: Object) []const Symbol.Index { |
| 747 | 759 | return self.symbols.items[start..]; |
| 748 | 760 | } |
| 749 | 761 | |
| 750 | fn shdrContents(self: Object, index: u32) error{Overflow}![]const u8 { | |
| 762 | pub fn shdrContents(self: Object, index: u32) []const u8 { | |
| 751 | 763 | assert(index < self.shdrs.items.len); |
| 752 | 764 | const shdr = self.shdrs.items[index]; |
| 753 | const offset = math.cast(usize, shdr.sh_offset) orelse return error.Overflow; | |
| 754 | const size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; | |
| 755 | return self.data[offset..][0..size]; | |
| 765 | return self.data[shdr.sh_offset..][0..shdr.sh_size]; | |
| 756 | 766 | } |
| 757 | 767 | |
| 758 | 768 | /// Returns atom's code and optionally uncompresses data if required (for compressed sections). |
| ... | ... | @@ -761,7 +771,7 @@ pub fn codeDecompressAlloc(self: Object, elf_file: *Elf, atom_index: Atom.Index) |
| 761 | 771 | const gpa = elf_file.base.allocator; |
| 762 | 772 | const atom_ptr = elf_file.atom(atom_index).?; |
| 763 | 773 | assert(atom_ptr.file_index == self.index); |
| 764 | const data = try self.shdrContents(atom_ptr.input_section_index); | |
| 774 | const data = self.shdrContents(atom_ptr.input_section_index); | |
| 765 | 775 | const shdr = atom_ptr.inputShdr(elf_file); |
| 766 | 776 | if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) { |
| 767 | 777 | const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*; |
| ... | ... | @@ -789,8 +799,8 @@ fn getString(self: *Object, off: u32) [:0]const u8 { |
| 789 | 799 | return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.ptr + off)), 0); |
| 790 | 800 | } |
| 791 | 801 | |
| 792 | pub fn comdatGroupMembers(self: *Object, index: u16) error{Overflow}![]align(1) const u32 { | |
| 793 | const raw = try self.shdrContents(index); | |
| 802 | pub fn comdatGroupMembers(self: *Object, index: u16) []align(1) const u32 { | |
| 803 | const raw = self.shdrContents(index); | |
| 794 | 804 | const nmembers = @divExact(raw.len, @sizeOf(u32)); |
| 795 | 805 | const members = @as([*]align(1) const u32, @ptrCast(raw.ptr))[1..nmembers]; |
| 796 | 806 | return members; |
| ... | ... | @@ -800,8 +810,8 @@ pub fn asFile(self: *Object) File { |
| 800 | 810 | return .{ .object = self }; |
| 801 | 811 | } |
| 802 | 812 | |
| 803 | pub fn getRelocs(self: *Object, shndx: u32) error{Overflow}![]align(1) const elf.Elf64_Rela { | |
| 804 | const raw = try self.shdrContents(shndx); | |
| 813 | pub fn getRelocs(self: *Object, shndx: u32) []align(1) const elf.Elf64_Rela { | |
| 814 | const raw = self.shdrContents(shndx); | |
| 805 | 815 | const num = @divExact(raw.len, @sizeOf(elf.Elf64_Rela)); |
| 806 | 816 | return @as([*]align(1) const elf.Elf64_Rela, @ptrCast(raw.ptr))[0..num]; |
| 807 | 817 | } |
| ... | ... | @@ -941,7 +951,7 @@ fn formatComdatGroups( |
| 941 | 951 | const cg = elf_file.comdatGroup(cg_index); |
| 942 | 952 | const cg_owner = elf_file.comdatGroupOwner(cg.owner); |
| 943 | 953 | if (cg_owner.file != object.index) continue; |
| 944 | const cg_members = object.comdatGroupMembers(cg.shndx) catch continue; | |
| 954 | const cg_members = object.comdatGroupMembers(cg.shndx); | |
| 945 | 955 | for (cg_members) |shndx| { |
| 946 | 956 | const atom_index = object.atoms.items[shndx]; |
| 947 | 957 | const atom = elf_file.atom(atom_index) orelse continue; |
| ... | ... | @@ -970,6 +980,34 @@ fn formatPath( |
| 970 | 980 | } else try writer.writeAll(object.path); |
| 971 | 981 | } |
| 972 | 982 | |
| 983 | pub const ElfShdr = struct { | |
| 984 | sh_name: u32, | |
| 985 | sh_type: u32, | |
| 986 | sh_flags: u64, | |
| 987 | sh_addr: u64, | |
| 988 | sh_offset: usize, | |
| 989 | sh_size: usize, | |
| 990 | sh_link: u32, | |
| 991 | sh_info: u32, | |
| 992 | sh_addralign: u64, | |
| 993 | sh_entsize: u64, | |
| 994 | ||
| 995 | fn fromElf64Shdr(shdr: elf.Elf64_Shdr) error{Overflow}!ElfShdr { | |
| 996 | return .{ | |
| 997 | .sh_name = shdr.sh_name, | |
| 998 | .sh_type = shdr.sh_type, | |
| 999 | .sh_flags = shdr.sh_flags, | |
| 1000 | .sh_addr = shdr.sh_addr, | |
| 1001 | .sh_offset = math.cast(usize, shdr.sh_offset) orelse return error.Overflow, | |
| 1002 | .sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow, | |
| 1003 | .sh_link = shdr.sh_link, | |
| 1004 | .sh_info = shdr.sh_info, | |
| 1005 | .sh_addralign = shdr.sh_addralign, | |
| 1006 | .sh_entsize = shdr.sh_entsize, | |
| 1007 | }; | |
| 1008 | } | |
| 1009 | }; | |
| 1010 | ||
| 973 | 1011 | const Object = @This(); |
| 974 | 1012 | |
| 975 | 1013 | const std = @import("std"); |
src/link/Elf/ZigModule.zig+1-1| ... | ... | @@ -145,7 +145,7 @@ pub fn scanRelocs(self: *ZigModule, elf_file: *Elf, undefs: anytype) !void { |
| 145 | 145 | for (self.atoms.items) |atom_index| { |
| 146 | 146 | const atom = elf_file.atom(atom_index) orelse continue; |
| 147 | 147 | if (!atom.flags.alive) continue; |
| 148 | if (try atom.scanRelocsRequiresCode(elf_file)) { | |
| 148 | if (atom.scanRelocsRequiresCode(elf_file)) { | |
| 149 | 149 | // TODO ideally we don't have to fetch the code here. |
| 150 | 150 | // Perhaps it would make sense to save the code until flushModule where we |
| 151 | 151 | // would free all of generated code? |
src/link/Elf/eh_frame.zig+24-26| ... | ... | @@ -20,9 +20,9 @@ pub const Fde = struct { |
| 20 | 20 | return base + fde.out_offset; |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | pub fn data(fde: Fde, elf_file: *Elf) error{Overflow}![]const u8 { | |
| 23 | pub fn data(fde: Fde, elf_file: *Elf) []const u8 { | |
| 24 | 24 | const object = elf_file.file(fde.file_index).?.object; |
| 25 | const contents = try object.shdrContents(fde.input_section_index); | |
| 25 | const contents = object.shdrContents(fde.input_section_index); | |
| 26 | 26 | return contents[fde.offset..][0..fde.calcSize()]; |
| 27 | 27 | } |
| 28 | 28 | |
| ... | ... | @@ -32,24 +32,25 @@ pub const Fde = struct { |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | 34 | pub fn ciePointer(fde: Fde, elf_file: *Elf) u32 { |
| 35 | return std.mem.readIntLittle(u32, fde.data(elf_file)[4..8]); | |
| 35 | const fde_data = fde.data(elf_file); | |
| 36 | return std.mem.readIntLittle(u32, fde_data[4..8]); | |
| 36 | 37 | } |
| 37 | 38 | |
| 38 | 39 | pub fn calcSize(fde: Fde) u64 { |
| 39 | 40 | return fde.size + 4; |
| 40 | 41 | } |
| 41 | 42 | |
| 42 | pub fn atom(fde: Fde, elf_file: *Elf) error{Overflow}!*Atom { | |
| 43 | pub fn atom(fde: Fde, elf_file: *Elf) *Atom { | |
| 43 | 44 | const object = elf_file.file(fde.file_index).?.object; |
| 44 | const rel = (try fde.relocs(elf_file))[0]; | |
| 45 | const rel = fde.relocs(elf_file)[0]; | |
| 45 | 46 | const sym = object.symtab[rel.r_sym()]; |
| 46 | 47 | const atom_index = object.atoms.items[sym.st_shndx]; |
| 47 | 48 | return elf_file.atom(atom_index).?; |
| 48 | 49 | } |
| 49 | 50 | |
| 50 | pub fn relocs(fde: Fde, elf_file: *Elf) error{Overflow}![]align(1) const elf.Elf64_Rela { | |
| 51 | pub fn relocs(fde: Fde, elf_file: *Elf) []align(1) const elf.Elf64_Rela { | |
| 51 | 52 | const object = elf_file.file(fde.file_index).?.object; |
| 52 | return (try object.getRelocs(fde.rel_section_index))[fde.rel_index..][0..fde.rel_num]; | |
| 53 | return object.getRelocs(fde.rel_section_index)[fde.rel_index..][0..fde.rel_num]; | |
| 53 | 54 | } |
| 54 | 55 | |
| 55 | 56 | pub fn format( |
| ... | ... | @@ -88,10 +89,7 @@ pub const Fde = struct { |
| 88 | 89 | const fde = ctx.fde; |
| 89 | 90 | const elf_file = ctx.elf_file; |
| 90 | 91 | const base_addr = fde.address(elf_file); |
| 91 | const atom_name = if (fde.atom(elf_file)) |atom_ptr| | |
| 92 | atom_ptr.name(elf_file) | |
| 93 | else |_| | |
| 94 | ""; | |
| 92 | const atom_name = fde.atom(elf_file).name(elf_file); | |
| 95 | 93 | try writer.print("@{x} : size({x}) : cie({d}) : {s}", .{ |
| 96 | 94 | base_addr + fde.out_offset, |
| 97 | 95 | fde.calcSize(), |
| ... | ... | @@ -123,9 +121,9 @@ pub const Cie = struct { |
| 123 | 121 | return base + cie.out_offset; |
| 124 | 122 | } |
| 125 | 123 | |
| 126 | pub fn data(cie: Cie, elf_file: *Elf) error{Overflow}![]const u8 { | |
| 124 | pub fn data(cie: Cie, elf_file: *Elf) []const u8 { | |
| 127 | 125 | const object = elf_file.file(cie.file_index).?.object; |
| 128 | const contents = try object.shdrContents(cie.input_section_index); | |
| 126 | const contents = object.shdrContents(cie.input_section_index); | |
| 129 | 127 | return contents[cie.offset..][0..cie.calcSize()]; |
| 130 | 128 | } |
| 131 | 129 | |
| ... | ... | @@ -133,16 +131,16 @@ pub const Cie = struct { |
| 133 | 131 | return cie.size + 4; |
| 134 | 132 | } |
| 135 | 133 | |
| 136 | pub fn relocs(cie: Cie, elf_file: *Elf) error{Overflow}![]align(1) const elf.Elf64_Rela { | |
| 134 | pub fn relocs(cie: Cie, elf_file: *Elf) []align(1) const elf.Elf64_Rela { | |
| 137 | 135 | const object = elf_file.file(cie.file_index).?.object; |
| 138 | return (try object.getRelocs(cie.rel_section_index))[cie.rel_index..][0..cie.rel_num]; | |
| 136 | return object.getRelocs(cie.rel_section_index)[cie.rel_index..][0..cie.rel_num]; | |
| 139 | 137 | } |
| 140 | 138 | |
| 141 | pub fn eql(cie: Cie, other: Cie, elf_file: *Elf) error{Overflow}!bool { | |
| 142 | if (!std.mem.eql(u8, try cie.data(elf_file), try other.data(elf_file))) return false; | |
| 139 | pub fn eql(cie: Cie, other: Cie, elf_file: *Elf) bool { | |
| 140 | if (!std.mem.eql(u8, cie.data(elf_file), other.data(elf_file))) return false; | |
| 143 | 141 | |
| 144 | const cie_relocs = try cie.relocs(elf_file); | |
| 145 | const other_relocs = try other.relocs(elf_file); | |
| 142 | const cie_relocs = cie.relocs(elf_file); | |
| 143 | const other_relocs = other.relocs(elf_file); | |
| 146 | 144 | if (cie_relocs.len != other_relocs.len) return false; |
| 147 | 145 | |
| 148 | 146 | for (cie_relocs, other_relocs) |cie_rel, other_rel| { |
| ... | ... | @@ -152,8 +150,8 @@ pub const Cie = struct { |
| 152 | 150 | |
| 153 | 151 | const cie_object = elf_file.file(cie.file_index).?.object; |
| 154 | 152 | const other_object = elf_file.file(other.file_index).?.object; |
| 155 | const cie_sym = cie_object.symbol(cie_rel.r_sym(), elf_file); | |
| 156 | const other_sym = other_object.symbol(other_rel.r_sym(), elf_file); | |
| 153 | const cie_sym = cie_object.symbols.items[cie_rel.r_sym()]; | |
| 154 | const other_sym = other_object.symbols.items[other_rel.r_sym()]; | |
| 157 | 155 | if (!std.mem.eql(u8, std.mem.asBytes(&cie_sym), std.mem.asBytes(&other_sym))) return false; |
| 158 | 156 | } |
| 159 | 157 | return true; |
| ... | ... | @@ -319,10 +317,10 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void { |
| 319 | 317 | for (object.cies.items) |cie| { |
| 320 | 318 | if (!cie.alive) continue; |
| 321 | 319 | |
| 322 | const contents = try gpa.dupe(u8, try cie.data(elf_file)); | |
| 320 | const contents = try gpa.dupe(u8, cie.data(elf_file)); | |
| 323 | 321 | defer gpa.free(contents); |
| 324 | 322 | |
| 325 | for (try cie.relocs(elf_file)) |rel| { | |
| 323 | for (cie.relocs(elf_file)) |rel| { | |
| 326 | 324 | const sym = object.symbol(rel.r_sym(), elf_file); |
| 327 | 325 | try resolveReloc(cie, sym, rel, elf_file, contents); |
| 328 | 326 | } |
| ... | ... | @@ -337,7 +335,7 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void { |
| 337 | 335 | for (object.fdes.items) |fde| { |
| 338 | 336 | if (!fde.alive) continue; |
| 339 | 337 | |
| 340 | const contents = try gpa.dupe(u8, try fde.data(elf_file)); | |
| 338 | const contents = try gpa.dupe(u8, fde.data(elf_file)); | |
| 341 | 339 | defer gpa.free(contents); |
| 342 | 340 | |
| 343 | 341 | std.mem.writeIntLittle( |
| ... | ... | @@ -346,7 +344,7 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void { |
| 346 | 344 | @as(i32, @truncate(@as(i64, @intCast(fde.out_offset + 4)) - @as(i64, @intCast(fde.cie(elf_file).out_offset)))), |
| 347 | 345 | ); |
| 348 | 346 | |
| 349 | for (try fde.relocs(elf_file)) |rel| { | |
| 347 | for (fde.relocs(elf_file)) |rel| { | |
| 350 | 348 | const sym = object.symbol(rel.r_sym(), elf_file); |
| 351 | 349 | try resolveReloc(fde, sym, rel, elf_file, contents); |
| 352 | 350 | } |
| ... | ... | @@ -395,7 +393,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void { |
| 395 | 393 | for (object.fdes.items) |fde| { |
| 396 | 394 | if (!fde.alive) continue; |
| 397 | 395 | |
| 398 | const relocs = try fde.relocs(elf_file); | |
| 396 | const relocs = fde.relocs(elf_file); | |
| 399 | 397 | assert(relocs.len > 0); // Should this be an error? Things are completely broken anyhow if this trips... |
| 400 | 398 | const rel = relocs[0]; |
| 401 | 399 | const sym = object.symbol(rel.r_sym(), elf_file); |