| ... | @@ -7,8 +7,8 @@ | ... | @@ -7,8 +7,8 @@ |
| 7 | path: []const u8, | 7 | path: []const u8, |
| 8 | index: File.Index, | 8 | index: File.Index, |
| 9 | | 9 | |
| 10 | local_esyms: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{}, | 10 | local_esyms: std.MultiArrayList(ElfSym) = .{}, |
| 11 | global_esyms: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{}, | 11 | global_esyms: std.MultiArrayList(ElfSym) = .{}, |
| 12 | local_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, | 12 | local_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 13 | global_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, | 13 | global_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 14 | globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{}, | 14 | globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{}, |
| ... | @@ -20,6 +20,10 @@ num_dynrelocs: u32 = 0, | ... | @@ -20,6 +20,10 @@ num_dynrelocs: u32 = 0, |
| 20 | | 20 | |
| 21 | output_symtab_size: Elf.SymtabSize = .{}, | 21 | output_symtab_size: Elf.SymtabSize = .{}, |
| 22 | | 22 | |
| | 23 | pub const global_symbol_bit: u32 = 0x80000000; |
| | 24 | pub const symbol_mask: u32 = 0x7fffffff; |
| | 25 | pub const SHN_ATOM: u16 = 0x100; |
| | 26 | |
| 23 | pub fn deinit(self: *ZigModule, allocator: Allocator) void { | 27 | pub fn deinit(self: *ZigModule, allocator: Allocator) void { |
| 24 | self.local_esyms.deinit(allocator); | 28 | self.local_esyms.deinit(allocator); |
| 25 | self.global_esyms.deinit(allocator); | 29 | self.global_esyms.deinit(allocator); |
| ... | @@ -35,20 +39,20 @@ pub fn deinit(self: *ZigModule, allocator: Allocator) void { | ... | @@ -35,20 +39,20 @@ pub fn deinit(self: *ZigModule, allocator: Allocator) void { |
| 35 | | 39 | |
| 36 | pub fn addLocalEsym(self: *ZigModule, allocator: Allocator) !Symbol.Index { | 40 | pub fn addLocalEsym(self: *ZigModule, allocator: Allocator) !Symbol.Index { |
| 37 | try self.local_esyms.ensureUnusedCapacity(allocator, 1); | 41 | try self.local_esyms.ensureUnusedCapacity(allocator, 1); |
| 38 | const index = @as(Symbol.Index, @intCast(self.local_esyms.items.len)); | 42 | const index = @as(Symbol.Index, @intCast(self.local_esyms.addOneAssumeCapacity())); |
| 39 | const esym = self.local_esyms.addOneAssumeCapacity(); | 43 | var esym = ElfSym{ .elf_sym = Elf.null_sym }; |
| 40 | esym.* = Elf.null_sym; | 44 | esym.elf_sym.st_info = elf.STB_LOCAL << 4; |
| 41 | esym.st_info = elf.STB_LOCAL << 4; | 45 | self.local_esyms.set(index, esym); |
| 42 | return index; | 46 | return index; |
| 43 | } | 47 | } |
| 44 | | 48 | |
| 45 | pub fn addGlobalEsym(self: *ZigModule, allocator: Allocator) !Symbol.Index { | 49 | pub fn addGlobalEsym(self: *ZigModule, allocator: Allocator) !Symbol.Index { |
| 46 | try self.global_esyms.ensureUnusedCapacity(allocator, 1); | 50 | try self.global_esyms.ensureUnusedCapacity(allocator, 1); |
| 47 | const index = @as(Symbol.Index, @intCast(self.global_esyms.items.len)); | 51 | const index = @as(Symbol.Index, @intCast(self.global_esyms.addOneAssumeCapacity())); |
| 48 | const esym = self.global_esyms.addOneAssumeCapacity(); | 52 | var esym = ElfSym{ .elf_sym = Elf.null_sym }; |
| 49 | esym.* = Elf.null_sym; | 53 | esym.elf_sym.st_info = elf.STB_GLOBAL << 4; |
| 50 | esym.st_info = elf.STB_GLOBAL << 4; | 54 | self.global_esyms.set(index, esym); |
| 51 | return index | 0x10000000; | 55 | return index | global_symbol_bit; |
| 52 | } | 56 | } |
| 53 | | 57 | |
| 54 | pub fn addAtom(self: *ZigModule, elf_file: *Elf) !Symbol.Index { | 58 | pub fn addAtom(self: *ZigModule, elf_file: *Elf) !Symbol.Index { |
| ... | @@ -58,7 +62,7 @@ pub fn addAtom(self: *ZigModule, elf_file: *Elf) !Symbol.Index { | ... | @@ -58,7 +62,7 @@ pub fn addAtom(self: *ZigModule, elf_file: *Elf) !Symbol.Index { |
| 58 | const symbol_index = try elf_file.addSymbol(); | 62 | const symbol_index = try elf_file.addSymbol(); |
| 59 | const esym_index = try self.addLocalEsym(gpa); | 63 | const esym_index = try self.addLocalEsym(gpa); |
| 60 | | 64 | |
| 61 | const shndx = @as(u16, @intCast(self.atoms.items.len)); | 65 | const shndx = @as(u32, @intCast(self.atoms.items.len)); |
| 62 | try self.atoms.append(gpa, atom_index); | 66 | try self.atoms.append(gpa, atom_index); |
| 63 | try self.local_symbols.append(gpa, symbol_index); | 67 | try self.local_symbols.append(gpa, symbol_index); |
| 64 | | 68 | |
| ... | @@ -69,11 +73,11 @@ pub fn addAtom(self: *ZigModule, elf_file: *Elf) !Symbol.Index { | ... | @@ -69,11 +73,11 @@ pub fn addAtom(self: *ZigModule, elf_file: *Elf) !Symbol.Index { |
| 69 | symbol_ptr.file_index = self.index; | 73 | symbol_ptr.file_index = self.index; |
| 70 | symbol_ptr.atom_index = atom_index; | 74 | symbol_ptr.atom_index = atom_index; |
| 71 | | 75 | |
| 72 | const esym = &self.local_esyms.items[esym_index]; | 76 | self.local_esyms.items(.shndx)[esym_index] = shndx; |
| 73 | esym.st_shndx = shndx; | 77 | self.local_esyms.items(.elf_sym)[esym_index].st_shndx = SHN_ATOM; |
| 74 | symbol_ptr.esym_index = esym_index; | 78 | symbol_ptr.esym_index = esym_index; |
| 75 | | 79 | |
| 76 | const relocs_index = @as(u16, @intCast(self.relocs.items.len)); | 80 | const relocs_index = @as(u32, @intCast(self.relocs.items.len)); |
| 77 | const relocs = try self.relocs.addOne(gpa); | 81 | const relocs = try self.relocs.addOne(gpa); |
| 78 | relocs.* = .{}; | 82 | relocs.* = .{}; |
| 79 | atom_ptr.relocs_section_index = relocs_index; | 83 | atom_ptr.relocs_section_index = relocs_index; |
| ... | @@ -99,13 +103,15 @@ pub fn inputShdr(self: ZigModule, atom_index: Atom.Index, elf_file: *Elf) Object | ... | @@ -99,13 +103,15 @@ pub fn inputShdr(self: ZigModule, atom_index: Atom.Index, elf_file: *Elf) Object |
| 99 | | 103 | |
| 100 | pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void { | 104 | pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void { |
| 101 | for (self.globals(), 0..) |index, i| { | 105 | for (self.globals(), 0..) |index, i| { |
| 102 | const esym_index = @as(Symbol.Index, @intCast(i)) | 0x10000000; | 106 | const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit; |
| 103 | const esym = self.global_esyms.items[i]; | 107 | const esym = self.global_esyms.items(.elf_sym)[i]; |
| | 108 | const shndx = self.global_esyms.items(.shndx)[i]; |
| 104 | | 109 | |
| 105 | if (esym.st_shndx == elf.SHN_UNDEF) continue; | 110 | if (esym.st_shndx == elf.SHN_UNDEF) continue; |
| 106 | | 111 | |
| 107 | if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) { | 112 | if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) { |
| 108 | const atom_index = self.atoms.items[esym.st_shndx]; | 113 | assert(esym.st_shndx == SHN_ATOM); |
| | 114 | const atom_index = self.atoms.items[shndx]; |
| 109 | const atom = elf_file.atom(atom_index) orelse continue; | 115 | const atom = elf_file.atom(atom_index) orelse continue; |
| 110 | if (!atom.flags.alive) continue; | 116 | if (!atom.flags.alive) continue; |
| 111 | } | 117 | } |
| ... | @@ -114,7 +120,8 @@ pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void { | ... | @@ -114,7 +120,8 @@ pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void { |
| 114 | if (self.asFile().symbolRank(esym, false) < global.symbolRank(elf_file)) { | 120 | if (self.asFile().symbolRank(esym, false) < global.symbolRank(elf_file)) { |
| 115 | const atom_index = switch (esym.st_shndx) { | 121 | const atom_index = switch (esym.st_shndx) { |
| 116 | elf.SHN_ABS, elf.SHN_COMMON => 0, | 122 | elf.SHN_ABS, elf.SHN_COMMON => 0, |
| 117 | else => self.atoms.items[esym.st_shndx], | 123 | SHN_ATOM => self.atoms.items[shndx], |
| | 124 | else => unreachable, |
| 118 | }; | 125 | }; |
| 119 | const output_section_index = if (elf_file.atom(atom_index)) |atom| | 126 | const output_section_index = if (elf_file.atom(atom_index)) |atom| |
| 120 | atom.outputShndx().? | 127 | atom.outputShndx().? |
| ... | @@ -133,8 +140,8 @@ pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void { | ... | @@ -133,8 +140,8 @@ pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void { |
| 133 | | 140 | |
| 134 | pub fn claimUnresolved(self: *ZigModule, elf_file: *Elf) void { | 141 | pub fn claimUnresolved(self: *ZigModule, elf_file: *Elf) void { |
| 135 | for (self.globals(), 0..) |index, i| { | 142 | for (self.globals(), 0..) |index, i| { |
| 136 | const esym_index = @as(Symbol.Index, @intCast(i)) | 0x10000000; | 143 | const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit; |
| 137 | const esym = self.global_esyms.items[i]; | 144 | const esym = self.global_esyms.items(.elf_sym)[i]; |
| 138 | | 145 | |
| 139 | if (esym.st_shndx != elf.SHN_UNDEF) continue; | 146 | if (esym.st_shndx != elf.SHN_UNDEF) continue; |
| 140 | | 147 | |
| ... | @@ -187,7 +194,7 @@ pub fn resetGlobals(self: *ZigModule, elf_file: *Elf) void { | ... | @@ -187,7 +194,7 @@ pub fn resetGlobals(self: *ZigModule, elf_file: *Elf) void { |
| 187 | | 194 | |
| 188 | pub fn markLive(self: *ZigModule, elf_file: *Elf) void { | 195 | pub fn markLive(self: *ZigModule, elf_file: *Elf) void { |
| 189 | for (self.globals(), 0..) |index, i| { | 196 | for (self.globals(), 0..) |index, i| { |
| 190 | const esym = self.global_esyms.items[i]; | 197 | const esym = self.global_esyms.items(.elf_sym)[i]; |
| 191 | if (esym.st_bind() == elf.STB_WEAK) continue; | 198 | if (esym.st_bind() == elf.STB_WEAK) continue; |
| 192 | | 199 | |
| 193 | const global = elf_file.symbol(index); | 200 | const global = elf_file.symbol(index); |
| ... | @@ -256,17 +263,17 @@ pub fn writeSymtab(self: *ZigModule, elf_file: *Elf, ctx: anytype) void { | ... | @@ -256,17 +263,17 @@ pub fn writeSymtab(self: *ZigModule, elf_file: *Elf, ctx: anytype) void { |
| 256 | } | 263 | } |
| 257 | | 264 | |
| 258 | pub fn symbol(self: *ZigModule, index: Symbol.Index) Symbol.Index { | 265 | pub fn symbol(self: *ZigModule, index: Symbol.Index) Symbol.Index { |
| 259 | const is_global = index & 0x10000000 != 0; | 266 | const is_global = index & global_symbol_bit != 0; |
| 260 | const actual_index = index & 0x0fffffff; | 267 | const actual_index = index & symbol_mask; |
| 261 | if (is_global) return self.global_symbols.items[actual_index]; | 268 | if (is_global) return self.global_symbols.items[actual_index]; |
| 262 | return self.local_symbols.items[actual_index]; | 269 | return self.local_symbols.items[actual_index]; |
| 263 | } | 270 | } |
| 264 | | 271 | |
| 265 | pub fn elfSym(self: *ZigModule, index: Symbol.Index) *elf.Elf64_Sym { | 272 | pub fn elfSym(self: *ZigModule, index: Symbol.Index) *elf.Elf64_Sym { |
| 266 | const is_global = index & 0x10000000 != 0; | 273 | const is_global = index & global_symbol_bit != 0; |
| 267 | const actual_index = index & 0x0fffffff; | 274 | const actual_index = index & symbol_mask; |
| 268 | if (is_global) return &self.global_esyms.items[actual_index]; | 275 | if (is_global) return &self.global_esyms.items(.elf_sym)[actual_index]; |
| 269 | return &self.local_esyms.items[actual_index]; | 276 | return &self.local_esyms.items(.elf_sym)[actual_index]; |
| 270 | } | 277 | } |
| 271 | | 278 | |
| 272 | pub fn locals(self: *ZigModule) []const Symbol.Index { | 279 | pub fn locals(self: *ZigModule) []const Symbol.Index { |
| ... | @@ -354,6 +361,11 @@ fn formatAtoms( | ... | @@ -354,6 +361,11 @@ fn formatAtoms( |
| 354 | } | 361 | } |
| 355 | } | 362 | } |
| 356 | | 363 | |
| | 364 | const ElfSym = struct { |
| | 365 | elf_sym: elf.Elf64_Sym, |
| | 366 | shndx: u32 = elf.SHN_UNDEF, |
| | 367 | }; |
| | 368 | |
| 357 | const assert = std.debug.assert; | 369 | const assert = std.debug.assert; |
| 358 | const std = @import("std"); | 370 | const std = @import("std"); |
| 359 | const elf = std.elf; | 371 | const elf = std.elf; |