diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-10-17 17:36:40 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-10-17 17:36:40 +0200 |
| commit | eb5276c94eaab238551fdae9a2e77b0133e31cfb (patch) | |
| tree | a8040cc914bb1db73b2484087cf81d5f20bab28c /src/link/Elf/ZigModule.zig | |
| parent | 5039a5db8365413794b0522a51137d3e97d8ba5d (diff) | |
| parent | 742a130ce55ae776372f99b0724c32a462040caf (diff) | |
| download | zig-eb5276c94eaab238551fdae9a2e77b0133e31cfb.tar.gz zig-eb5276c94eaab238551fdae9a2e77b0133e31cfb.zip | |
Merge pull request #17556 from ziglang/elf-link-zig-proper
elf: port 99% of zld ELF linker to Zig proper
Diffstat (limited to 'src/link/Elf/ZigModule.zig')
| -rw-r--r-- | src/link/Elf/ZigModule.zig | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/src/link/Elf/ZigModule.zig b/src/link/Elf/ZigModule.zig index c79680dbf5..4532d7b448 100644 --- a/src/link/Elf/ZigModule.zig +++ b/src/link/Elf/ZigModule.zig @@ -13,9 +13,11 @@ local_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, global_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{}, -atoms: std.AutoArrayHashMapUnmanaged(Atom.Index, void) = .{}, +atoms: std.ArrayListUnmanaged(Atom.Index) = .{}, relocs: std.ArrayListUnmanaged(std.ArrayListUnmanaged(elf.Elf64_Rela)) = .{}, +num_dynrelocs: u32 = 0, + output_symtab_size: Elf.SymtabSize = .{}, pub fn deinit(self: *ZigModule, allocator: Allocator) void { @@ -56,7 +58,8 @@ pub fn addAtom(self: *ZigModule, elf_file: *Elf) !Symbol.Index { const symbol_index = try elf_file.addSymbol(); const esym_index = try self.addLocalEsym(gpa); - try self.atoms.putNoClobber(gpa, atom_index, {}); + const shndx = @as(u16, @intCast(self.atoms.items.len)); + try self.atoms.append(gpa, atom_index); try self.local_symbols.append(gpa, symbol_index); const atom_ptr = elf_file.atom(atom_index).?; @@ -67,10 +70,10 @@ pub fn addAtom(self: *ZigModule, elf_file: *Elf) !Symbol.Index { symbol_ptr.atom_index = atom_index; const esym = &self.local_esyms.items[esym_index]; - esym.st_shndx = atom_index; + esym.st_shndx = shndx; symbol_ptr.esym_index = esym_index; - const relocs_index = @as(Atom.Index, @intCast(self.relocs.items.len)); + const relocs_index = @as(u16, @intCast(self.relocs.items.len)); const relocs = try self.relocs.addOne(gpa); relocs.* = .{}; atom_ptr.relocs_section_index = relocs_index; @@ -78,6 +81,22 @@ pub fn addAtom(self: *ZigModule, elf_file: *Elf) !Symbol.Index { return symbol_index; } +/// TODO actually create fake input shdrs and return that instead. +pub fn inputShdr(self: ZigModule, atom_index: Atom.Index, elf_file: *Elf) Object.ElfShdr { + _ = self; + const shdr = shdr: { + const atom = elf_file.atom(atom_index) orelse break :shdr Elf.null_shdr; + const shndx = atom.outputShndx() orelse break :shdr Elf.null_shdr; + var shdr = elf_file.shdrs.items[shndx]; + shdr.sh_addr = 0; + shdr.sh_offset = 0; + shdr.sh_size = atom.size; + shdr.sh_addralign = atom.alignment.toByteUnits(1); + break :shdr shdr; + }; + return Object.ElfShdr.fromElf64Shdr(shdr) catch unreachable; +} + pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void { for (self.globals(), 0..) |index, i| { const esym_index = @as(Symbol.Index, @intCast(i)) | 0x10000000; @@ -86,7 +105,7 @@ pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void { if (esym.st_shndx == elf.SHN_UNDEF) continue; if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) { - const atom_index = esym.st_shndx; + const atom_index = self.atoms.items[esym.st_shndx]; const atom = elf_file.atom(atom_index) orelse continue; if (!atom.flags.alive) continue; } @@ -95,7 +114,7 @@ pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void { if (self.asFile().symbolRank(esym, false) < global.symbolRank(elf_file)) { const atom_index = switch (esym.st_shndx) { elf.SHN_ABS, elf.SHN_COMMON => 0, - else => esym.st_shndx, + else => self.atoms.items[esym.st_shndx], }; const output_section_index = if (elf_file.atom(atom_index)) |atom| atom.outputShndx().? @@ -141,10 +160,12 @@ pub fn claimUnresolved(self: *ZigModule, elf_file: *Elf) void { } pub fn scanRelocs(self: *ZigModule, elf_file: *Elf, undefs: anytype) !void { - for (self.atoms.keys()) |atom_index| { + for (self.atoms.items) |atom_index| { const atom = elf_file.atom(atom_index) orelse continue; if (!atom.flags.alive) continue; - if (try atom.scanRelocsRequiresCode(elf_file)) { + const shdr = atom.inputShdr(elf_file); + if (shdr.sh_type == elf.SHT_NOBITS) continue; + if (atom.scanRelocsRequiresCode(elf_file)) { // TODO ideally we don't have to fetch the code here. // Perhaps it would make sense to save the code until flushModule where we // would free all of generated code? @@ -272,7 +293,10 @@ pub fn codeAlloc(self: ZigModule, elf_file: *Elf, atom_index: Atom.Index) ![]u8 const code = try gpa.alloc(u8, size); errdefer gpa.free(code); const amt = try elf_file.base.file.?.preadAll(code, file_offset); - if (amt != code.len) return error.InputOutput; + if (amt != code.len) { + log.err("fetching code for {s} failed", .{atom.name(elf_file)}); + return error.InputOutput; + } return code; } @@ -324,7 +348,7 @@ fn formatAtoms( _ = unused_fmt_string; _ = options; try writer.writeAll(" atoms\n"); - for (ctx.self.atoms.keys()) |atom_index| { + for (ctx.self.atoms.items) |atom_index| { const atom = ctx.elf_file.atom(atom_index) orelse continue; try writer.print(" {}\n", .{atom.fmt(ctx.elf_file)}); } @@ -333,11 +357,13 @@ fn formatAtoms( const assert = std.debug.assert; const std = @import("std"); const elf = std.elf; +const log = std.log.scoped(.link); const Allocator = std.mem.Allocator; const Atom = @import("Atom.zig"); const Elf = @import("../Elf.zig"); const File = @import("file.zig").File; const Module = @import("../../Module.zig"); +const Object = @import("Object.zig"); const Symbol = @import("Symbol.zig"); const ZigModule = @This(); |
