| ... | ... | @@ -8,9 +8,11 @@ data: std.ArrayListUnmanaged(u8) = .{}, |
| 8 | 8 | path: []const u8, |
| 9 | 9 | index: File.Index, |
| 10 | 10 | |
| 11 | | local_esyms: std.MultiArrayList(ElfSym) = .{}, |
| 12 | | global_esyms: std.MultiArrayList(ElfSym) = .{}, |
| 11 | symtab: std.MultiArrayList(ElfSym) = .{}, |
| 13 | 12 | strtab: StringTable = .{}, |
| 13 | symbols: std.ArrayListUnmanaged(Symbol) = .{}, |
| 14 | symbols_extra: std.ArrayListUnmanaged(u32) = .{}, |
| 15 | symbols_resolver: std.ArrayListUnmanaged(Elf.SymbolResolver.Index) = .{}, |
| 14 | 16 | local_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 15 | 17 | global_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 16 | 18 | globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{}, |
| ... | ... | @@ -113,9 +115,11 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void { |
| 113 | 115 | |
| 114 | 116 | pub fn deinit(self: *ZigObject, allocator: Allocator) void { |
| 115 | 117 | self.data.deinit(allocator); |
| 116 | | self.local_esyms.deinit(allocator); |
| 117 | | self.global_esyms.deinit(allocator); |
| 118 | self.symtab.deinit(allocator); |
| 118 | 119 | self.strtab.deinit(allocator); |
| 120 | self.symbols.deinit(allocator); |
| 121 | self.symbols_extra.deinit(allocator); |
| 122 | self.symbols_resolver.deinit(allocator); |
| 119 | 123 | self.local_symbols.deinit(allocator); |
| 120 | 124 | self.global_symbols.deinit(allocator); |
| 121 | 125 | self.globals_lookup.deinit(allocator); |
| ... | ... | @@ -263,51 +267,73 @@ fn saveDebugSectionsSizes(self: *ZigObject, elf_file: *Elf) void { |
| 263 | 267 | } |
| 264 | 268 | } |
| 265 | 269 | |
| 266 | | pub fn addLocalEsym(self: *ZigObject, allocator: Allocator) !Symbol.Index { |
| 267 | | try self.local_esyms.ensureUnusedCapacity(allocator, 1); |
| 268 | | const index = @as(Symbol.Index, @intCast(self.local_esyms.addOneAssumeCapacity())); |
| 269 | | var esym = ElfSym{ .elf_sym = Elf.null_sym }; |
| 270 | | esym.elf_sym.st_info = elf.STB_LOCAL << 4; |
| 271 | | self.local_esyms.set(index, esym); |
| 270 | fn newSymbol(self: *ZigObject, allocator: Allocator, name_off: u32, st_bind: u4) !Symbol.Index { |
| 271 | try self.symtab.ensureUnusedCapacity(allocator, 1); |
| 272 | try self.symbols.ensureUnusedCapacity(allocator, 1); |
| 273 | try self.symbols_extra.ensureUnusedCapacity(allocator, @sizeOf(Symbol.Extra)); |
| 274 | |
| 275 | const index = self.addSymbolAssumeCapacity(); |
| 276 | const sym = &self.symbols.items[index]; |
| 277 | sym.name_offset = name_off; |
| 278 | sym.extra = self.addSymbolExtraAssumeCapacity(.{}); |
| 279 | |
| 280 | const esym_idx: u32 = @intCast(self.symtab.addOneAssumeCapacity()); |
| 281 | const esym = ElfSym{ .elf_sym = .{ |
| 282 | .st_value = 0, |
| 283 | .st_name = name_off, |
| 284 | .st_info = @as(u8, @intCast(st_bind)) << 4, |
| 285 | .st_other = 0, |
| 286 | .st_size = 0, |
| 287 | .st_shndx = 0, |
| 288 | } }; |
| 289 | self.symtab.set(index, esym); |
| 290 | sym.esym_index = esym_idx; |
| 291 | |
| 272 | 292 | return index; |
| 273 | 293 | } |
| 274 | 294 | |
| 275 | | pub fn addGlobalEsym(self: *ZigObject, allocator: Allocator) !Symbol.Index { |
| 276 | | try self.global_esyms.ensureUnusedCapacity(allocator, 1); |
| 277 | | const index = @as(Symbol.Index, @intCast(self.global_esyms.addOneAssumeCapacity())); |
| 278 | | var esym = ElfSym{ .elf_sym = Elf.null_sym }; |
| 279 | | esym.elf_sym.st_info = elf.STB_GLOBAL << 4; |
| 280 | | self.global_esyms.set(index, esym); |
| 281 | | return index | global_symbol_bit; |
| 295 | fn newLocalSymbol(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index { |
| 296 | try self.local_symbols.ensureUnusedCapacity(allocator, 1); |
| 297 | const fake_index: Symbol.Index = @intCast(self.local_symbols.items.len); |
| 298 | const index = try self.newSymbol(allocator, name_off, elf.STB_LOCAL); |
| 299 | self.local_symbols.appendAssumeCapacity(index); |
| 300 | return fake_index; |
| 282 | 301 | } |
| 283 | 302 | |
| 284 | | pub fn newAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index { |
| 285 | | const gpa = elf_file.base.comp.gpa; |
| 286 | | const atom_index = try self.addAtom(gpa); |
| 287 | | const symbol_index = try elf_file.addSymbol(); |
| 288 | | const esym_index = try self.addLocalEsym(gpa); |
| 289 | | |
| 290 | | try self.atoms_indexes.append(gpa, atom_index); |
| 291 | | try self.local_symbols.append(gpa, symbol_index); |
| 292 | | |
| 293 | | const symbol_ptr = elf_file.symbol(symbol_index); |
| 294 | | symbol_ptr.file_index = self.index; |
| 295 | | symbol_ptr.ref = .{ .index = atom_index, .file = self.index }; |
| 296 | | symbol_ptr.extra_index = try elf_file.addSymbolExtra(.{}); |
| 303 | fn newGlobalSymbol(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index { |
| 304 | try self.global_symbols.ensureUnusedCapacity(allocator, 1); |
| 305 | const fake_index: Symbol.Index = @intCast(self.global_symbols.items.len); |
| 306 | const index = try self.newSymbol(allocator, name_off, elf.STB_GLOBAL); |
| 307 | self.global_symbols.appendAssumeCapacity(index); |
| 308 | return fake_index | global_symbol_bit; |
| 309 | } |
| 297 | 310 | |
| 298 | | self.local_esyms.items(.shndx)[esym_index] = atom_index; |
| 299 | | self.local_esyms.items(.elf_sym)[esym_index].st_shndx = SHN_ATOM; |
| 300 | | symbol_ptr.esym_index = esym_index; |
| 311 | fn newAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Atom.Index { |
| 312 | try self.atoms.ensureUnusedCapacity(allocator, 1); |
| 313 | try self.atoms_extra.ensureUnusedCapacity(allocator, @sizeOf(Atom.Extra)); |
| 314 | try self.atoms_indexes.ensureUnusedCapacity(allocator, 1); |
| 315 | try self.relocs.ensureUnusedCapacity(allocator, 1); |
| 301 | 316 | |
| 302 | | // TODO I'm thinking that maybe we shouldn' set this value unless it's actually needed? |
| 303 | | const relocs_index = @as(u32, @intCast(self.relocs.items.len)); |
| 304 | | const relocs = try self.relocs.addOne(gpa); |
| 305 | | relocs.* = .{}; |
| 317 | const index = self.addAtomAssumeCapacity(); |
| 318 | self.atoms_indexes.appendAssumeCapacity(index); |
| 319 | const atom_ptr = self.atom(index).?; |
| 320 | atom_ptr.name_offset = name_off; |
| 306 | 321 | |
| 307 | | const atom_ptr = self.atom(atom_index).?; |
| 322 | const relocs_index: u32 = @intCast(self.relocs.items.len); |
| 323 | self.relocs.addOneAssumeCapacity().* = .{}; |
| 308 | 324 | atom_ptr.relocs_section_index = relocs_index; |
| 309 | 325 | |
| 310 | | return symbol_index; |
| 326 | return index; |
| 327 | } |
| 328 | |
| 329 | fn newSymbolWithAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index { |
| 330 | const atom_index = try self.newAtom(allocator, name_off); |
| 331 | const sym_index = try self.newLocalSymbol(allocator, name_off); |
| 332 | const sym = self.symbol(sym_index); |
| 333 | sym.ref = .{ .index = atom_index, .file = self.index }; |
| 334 | self.symtab.items(.shndx)[sym.esym_index] = atom_index; |
| 335 | self.symtab.items(.elf_sym)[sym.esym_index].st_shndx = SHN_ATOM; |
| 336 | return sym_index; |
| 311 | 337 | } |
| 312 | 338 | |
| 313 | 339 | /// TODO actually create fake input shdrs and return that instead. |
| ... | ... | @@ -322,48 +348,47 @@ pub fn inputShdr(self: *ZigObject, atom_index: Atom.Index, elf_file: *Elf) elf.E |
| 322 | 348 | return shdr; |
| 323 | 349 | } |
| 324 | 350 | |
| 325 | | pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) void { |
| 326 | | for (self.globals(), 0..) |index, i| { |
| 327 | | const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit; |
| 328 | | const esym = self.global_esyms.items(.elf_sym)[i]; |
| 329 | | const shndx = self.global_esyms.items(.shndx)[i]; |
| 330 | | |
| 331 | | if (esym.st_shndx == elf.SHN_UNDEF) continue; |
| 351 | pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) !void { |
| 352 | const gpa = elf_file.base.comp.gpa; |
| 332 | 353 | |
| 354 | for (self.global_symbols.items, 0..) |index, i| { |
| 355 | const global = &self.symbols.items[index]; |
| 356 | const esym = global.elfSym(elf_file); |
| 357 | const shndx = self.symtab.items(.shndx)[global.esym_index]; |
| 333 | 358 | if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) { |
| 334 | 359 | assert(esym.st_shndx == SHN_ATOM); |
| 335 | 360 | const atom_ptr = self.atom(shndx) orelse continue; |
| 336 | 361 | if (!atom_ptr.alive) continue; |
| 337 | 362 | } |
| 338 | 363 | |
| 339 | | const global = elf_file.symbol(index); |
| 340 | | if (self.asFile().symbolRank(esym, false) < global.symbolRank(elf_file)) { |
| 341 | | const atom_index = switch (esym.st_shndx) { |
| 342 | | elf.SHN_ABS, elf.SHN_COMMON => 0, |
| 343 | | SHN_ATOM => shndx, |
| 344 | | else => unreachable, |
| 345 | | }; |
| 346 | | global.value = @intCast(esym.st_value); |
| 347 | | global.ref = .{ .index = atom_index, .file = self.index }; |
| 348 | | global.esym_index = esym_index; |
| 349 | | global.file_index = self.index; |
| 350 | | global.version_index = elf_file.default_sym_version; |
| 351 | | if (esym.st_bind() == elf.STB_WEAK) global.flags.weak = true; |
| 364 | const resolv = &self.symbols_resolver.items[i]; |
| 365 | const gop = try elf_file.resolver.getOrPut(gpa, .{ |
| 366 | .index = @intCast(i | global_symbol_bit), |
| 367 | .file = self.index, |
| 368 | }, elf_file); |
| 369 | if (!gop.found_existing) { |
| 370 | gop.ref.* = .{ .index = 0, .file = 0 }; |
| 371 | } |
| 372 | resolv.* = gop.index; |
| 373 | |
| 374 | if (esym.st_shndx == elf.SHN_UNDEF) continue; |
| 375 | if (elf_file.symbol(gop.ref.*) == null) { |
| 376 | gop.ref.* = .{ .index = @intCast(i | global_symbol_bit), .file = self.index }; |
| 377 | continue; |
| 378 | } |
| 379 | |
| 380 | if (self.asFile().symbolRank(esym, !self.alive) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) { |
| 381 | gop.ref.* = .{ .index = @intCast(i | global_symbol_bit), .file = self.index }; |
| 352 | 382 | } |
| 353 | 383 | } |
| 354 | 384 | } |
| 355 | 385 | |
| 356 | | pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void { |
| 357 | | for (self.globals(), 0..) |index, i| { |
| 358 | | const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit; |
| 359 | | const esym = self.global_esyms.items(.elf_sym)[i]; |
| 360 | | |
| 386 | pub fn claimUnresolved(self: *ZigObject, elf_file: *Elf) void { |
| 387 | for (self.global_symbols.items, 0..) |index, i| { |
| 388 | const global = &self.symbols.items[index]; |
| 389 | const esym = self.symtab.items(.elf_sym)[index]; |
| 361 | 390 | if (esym.st_shndx != elf.SHN_UNDEF) continue; |
| 362 | | |
| 363 | | const global = elf_file.symbol(index); |
| 364 | | if (global.file(elf_file)) |_| { |
| 365 | | if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF) continue; |
| 366 | | } |
| 391 | if (elf_file.symbol(self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file)) != null) continue; |
| 367 | 392 | |
| 368 | 393 | const is_import = blk: { |
| 369 | 394 | if (!elf_file.isEffectivelyDynLib()) break :blk false; |
| ... | ... | @@ -374,29 +399,36 @@ pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void { |
| 374 | 399 | |
| 375 | 400 | global.value = 0; |
| 376 | 401 | global.ref = .{ .index = 0, .file = 0 }; |
| 377 | | global.esym_index = esym_index; |
| 402 | global.esym_index = @intCast(index); |
| 378 | 403 | global.file_index = self.index; |
| 379 | 404 | global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version; |
| 380 | 405 | global.flags.import = is_import; |
| 406 | |
| 407 | const idx = self.symbols_resolver.items[i]; |
| 408 | elf_file.resolver.values.items[idx - 1] = .{ .index = @intCast(i | global_symbol_bit), .file = self.index }; |
| 381 | 409 | } |
| 382 | 410 | } |
| 383 | 411 | |
| 384 | 412 | pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void { |
| 385 | | for (self.globals(), 0..) |index, i| { |
| 386 | | const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit; |
| 387 | | const esym = self.global_esyms.items(.elf_sym)[i]; |
| 388 | | |
| 413 | for (self.global_symbols.items, 0..) |index, i| { |
| 414 | const global = &self.symbols.items[index]; |
| 415 | const esym = self.symtab.items(.elf_sym)[index]; |
| 389 | 416 | if (esym.st_shndx != elf.SHN_UNDEF) continue; |
| 417 | if (elf_file.symbol(self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file)) != null) continue; |
| 390 | 418 | |
| 391 | | const global = elf_file.symbol(index); |
| 392 | | if (global.file(elf_file)) |file| { |
| 393 | | if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF or file.index() <= self.index) continue; |
| 394 | | } |
| 419 | // TODO: audit this |
| 420 | // const global = elf_file.symbol(index); |
| 421 | // if (global.file(elf_file)) |file| { |
| 422 | // if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF or file.index() <= self.index) continue; |
| 423 | // } |
| 395 | 424 | |
| 396 | 425 | global.value = 0; |
| 397 | 426 | global.ref = .{ .index = 0, .file = 0 }; |
| 398 | | global.esym_index = esym_index; |
| 427 | global.esym_index = @intCast(index); |
| 399 | 428 | global.file_index = self.index; |
| 429 | |
| 430 | const idx = self.symbols_resolver.items[i]; |
| 431 | elf_file.resolver.items[idx - 1] = .{ .index = @intCast(i | global_symbol_bit), .file = self.index }; |
| 400 | 432 | } |
| 401 | 433 | } |
| 402 | 434 | |
| ... | ... | @@ -419,12 +451,14 @@ pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void { |
| 419 | 451 | } |
| 420 | 452 | |
| 421 | 453 | pub fn markLive(self: *ZigObject, elf_file: *Elf) void { |
| 422 | | for (self.globals(), 0..) |index, i| { |
| 423 | | const esym = self.global_esyms.items(.elf_sym)[i]; |
| 454 | for (self.global_symbols.items, 0..) |index, i| { |
| 455 | const global = self.symbols.items[index]; |
| 456 | const esym = self.symtab.items(.elf_sym)[index]; |
| 424 | 457 | if (esym.st_bind() == elf.STB_WEAK) continue; |
| 425 | 458 | |
| 426 | | const global = elf_file.symbol(index); |
| 427 | | const file = global.file(elf_file) orelse continue; |
| 459 | const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file); |
| 460 | const sym = elf_file.symbol(ref) orelse continue; |
| 461 | const file = sym.file(elf_file).?; |
| 428 | 462 | const should_keep = esym.st_shndx == elf.SHN_UNDEF or |
| 429 | 463 | (esym.st_shndx == elf.SHN_COMMON and global.elfSym(elf_file).st_shndx != elf.SHN_COMMON); |
| 430 | 464 | if (should_keep and !file.isAlive()) { |
| ... | ... | @@ -434,14 +468,36 @@ pub fn markLive(self: *ZigObject, elf_file: *Elf) void { |
| 434 | 468 | } |
| 435 | 469 | } |
| 436 | 470 | |
| 437 | | pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void { |
| 438 | | for (self.globals(), 0..) |index, i| { |
| 439 | | const esym = self.global_esyms.items(.elf_sym)[i]; |
| 440 | | const shndx = self.global_esyms.items(.shndx)[i]; |
| 441 | | const global = elf_file.symbol(index); |
| 442 | | const global_file = global.file(elf_file) orelse continue; |
| 471 | pub fn markImportsExports(self: *Object, elf_file: *Elf) void { |
| 472 | for (0..self.global_symbols.items.len) |i| { |
| 473 | const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file); |
| 474 | const sym = elf_file.symbol(ref) orelse continue; |
| 475 | const file = sym.file(elf_file).?; |
| 476 | if (sym.version_index == elf.VER_NDX_LOCAL) continue; |
| 477 | const vis = @as(elf.STV, @enumFromInt(sym.elfSym(elf_file).st_other)); |
| 478 | if (vis == .HIDDEN) continue; |
| 479 | if (file == .shared_object and !sym.isAbs(elf_file)) { |
| 480 | sym.flags.import = true; |
| 481 | continue; |
| 482 | } |
| 483 | if (file.index() == self.index) { |
| 484 | sym.flags.@"export" = true; |
| 485 | if (elf_file.isEffectivelyDynLib() and vis != .PROTECTED) { |
| 486 | sym.flags.import = true; |
| 487 | } |
| 488 | } |
| 489 | } |
| 490 | } |
| 443 | 491 | |
| 444 | | if (self.index == global_file.index() or |
| 492 | pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void { |
| 493 | for (self.global_symbols.items, 0..) |index, i| { |
| 494 | const esym = self.symtab.items(.elf_sym)[index]; |
| 495 | const shndx = self.symtab.items(.shndx)[index]; |
| 496 | const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file); |
| 497 | const ref_sym = elf_file.symbol(ref) orelse continue; |
| 498 | const ref_file = ref_sym.file(elf_file).?; |
| 499 | |
| 500 | if (self.index == ref_file.index() or |
| 445 | 501 | esym.st_shndx == elf.SHN_UNDEF or |
| 446 | 502 | esym.st_bind() == elf.STB_WEAK or |
| 447 | 503 | esym.st_shndx == elf.SHN_COMMON) continue; |
| ... | ... | @@ -451,7 +507,7 @@ pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{O |
| 451 | 507 | if (!atom_ptr.alive) continue; |
| 452 | 508 | } |
| 453 | 509 | |
| 454 | | const gop = try dupes.getOrPut(index); |
| 510 | const gop = try dupes.getOrPut(self.symbols_resolver.items[i]); |
| 455 | 511 | if (!gop.found_existing) { |
| 456 | 512 | gop.value_ptr.* = .{}; |
| 457 | 513 | } |
| ... | ... | @@ -483,12 +539,13 @@ pub fn readFileContents(self: *ZigObject, elf_file: *Elf) !void { |
| 483 | 539 | pub fn updateArSymtab(self: ZigObject, ar_symtab: *Archive.ArSymtab, elf_file: *Elf) error{OutOfMemory}!void { |
| 484 | 540 | const gpa = elf_file.base.comp.gpa; |
| 485 | 541 | |
| 486 | | try ar_symtab.symtab.ensureUnusedCapacity(gpa, self.globals().len); |
| 542 | try ar_symtab.symtab.ensureUnusedCapacity(gpa, self.global_symbols.items.len); |
| 487 | 543 | |
| 488 | | for (self.globals()) |global_index| { |
| 489 | | const global = elf_file.symbol(global_index); |
| 490 | | const file_ptr = global.file(elf_file).?; |
| 491 | | assert(file_ptr.index() == self.index); |
| 544 | for (self.global_symbols.items, 0..) |index, i| { |
| 545 | const global = self.symbols.items[index]; |
| 546 | const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file); |
| 547 | const sym = elf_file.symbol(ref).?; |
| 548 | assert(sym.file(elf_file).?.index() == self.index); |
| 492 | 549 | if (global.outputShndx(elf_file) == null) continue; |
| 493 | 550 | |
| 494 | 551 | const off = try ar_symtab.strtab.insert(gpa, global.name(elf_file)); |
| ... | ... | @@ -530,33 +587,9 @@ pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void { |
| 530 | 587 | } |
| 531 | 588 | } |
| 532 | 589 | |
| 533 | | inline fn isGlobal(index: Symbol.Index) bool { |
| 534 | | return index & global_symbol_bit != 0; |
| 535 | | } |
| 536 | | |
| 537 | | pub fn symbol(self: ZigObject, index: Symbol.Index) Symbol.Index { |
| 538 | | const actual_index = index & symbol_mask; |
| 539 | | if (isGlobal(index)) return self.globals()[actual_index]; |
| 540 | | return self.locals()[actual_index]; |
| 541 | | } |
| 542 | | |
| 543 | | pub fn elfSym(self: *ZigObject, index: Symbol.Index) *elf.Elf64_Sym { |
| 544 | | const actual_index = index & symbol_mask; |
| 545 | | if (isGlobal(index)) return &self.global_esyms.items(.elf_sym)[actual_index]; |
| 546 | | return &self.local_esyms.items(.elf_sym)[actual_index]; |
| 547 | | } |
| 548 | | |
| 549 | | pub fn locals(self: ZigObject) []const Symbol.Index { |
| 550 | | return self.local_symbols.items; |
| 551 | | } |
| 552 | | |
| 553 | | pub fn globals(self: ZigObject) []const Symbol.Index { |
| 554 | | return self.global_symbols.items; |
| 555 | | } |
| 556 | | |
| 557 | 590 | pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void { |
| 558 | | for (self.locals()) |local_index| { |
| 559 | | const local = elf_file.symbol(local_index); |
| 591 | for (self.local_symbols.items) |index| { |
| 592 | const local = &self.symbols.items[index]; |
| 560 | 593 | if (local.atom(elf_file)) |atom_ptr| if (!atom_ptr.alive) continue; |
| 561 | 594 | const esym = local.elfSym(elf_file); |
| 562 | 595 | switch (esym.st_type()) { |
| ... | ... | @@ -564,22 +597,23 @@ pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void { |
| 564 | 597 | else => {}, |
| 565 | 598 | } |
| 566 | 599 | local.flags.output_symtab = true; |
| 567 | | try local.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); |
| 600 | local.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); |
| 568 | 601 | self.output_symtab_ctx.nlocals += 1; |
| 569 | 602 | self.output_symtab_ctx.strsize += @as(u32, @intCast(local.name(elf_file).len)) + 1; |
| 570 | 603 | } |
| 571 | 604 | |
| 572 | | for (self.globals()) |global_index| { |
| 573 | | const global = elf_file.symbol(global_index); |
| 574 | | const file_ptr = global.file(elf_file) orelse continue; |
| 575 | | if (file_ptr.index() != self.index) continue; |
| 605 | for (self.global_symbols.items, self.symbols_resolver.items) |index, resolv| { |
| 606 | const global = &self.symbols.items[index]; |
| 607 | const ref = elf_file.resolver.items[resolv]; |
| 608 | const ref_sym = elf_file.symbol(ref) orelse continue; |
| 609 | if (ref_sym.file(elf_file).?.index() != self.index) continue; |
| 576 | 610 | if (global.atom(elf_file)) |atom_ptr| if (!atom_ptr.alive) continue; |
| 577 | 611 | global.flags.output_symtab = true; |
| 578 | 612 | if (global.isLocal(elf_file)) { |
| 579 | | try global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); |
| 613 | global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); |
| 580 | 614 | self.output_symtab_ctx.nlocals += 1; |
| 581 | 615 | } else { |
| 582 | | try global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file); |
| 616 | global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file); |
| 583 | 617 | self.output_symtab_ctx.nglobals += 1; |
| 584 | 618 | } |
| 585 | 619 | self.output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1; |
| ... | ... | @@ -587,8 +621,8 @@ pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void { |
| 587 | 621 | } |
| 588 | 622 | |
| 589 | 623 | pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void { |
| 590 | | for (self.locals()) |local_index| { |
| 591 | | const local = elf_file.symbol(local_index); |
| 624 | for (self.local_symbols.items) |index| { |
| 625 | const local = &self.symbols.items[index]; |
| 592 | 626 | const idx = local.outputSymtabIndex(elf_file) orelse continue; |
| 593 | 627 | const out_sym = &elf_file.symtab.items[idx]; |
| 594 | 628 | out_sym.st_name = @intCast(elf_file.strtab.items.len); |
| ... | ... | @@ -597,10 +631,11 @@ pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void { |
| 597 | 631 | local.setOutputSym(elf_file, out_sym); |
| 598 | 632 | } |
| 599 | 633 | |
| 600 | | for (self.globals()) |global_index| { |
| 601 | | const global = elf_file.symbol(global_index); |
| 602 | | const file_ptr = global.file(elf_file) orelse continue; |
| 603 | | if (file_ptr.index() != self.index) continue; |
| 634 | for (self.global_symbols.items, self.symbols_resolver.items) |index, resolv| { |
| 635 | const global = self.symbols.items[index]; |
| 636 | const ref = elf_file.resolver.items[resolv]; |
| 637 | const ref_sym = elf_file.symbol(ref) orelse continue; |
| 638 | if (ref_sym.file(elf_file).?.index() != self.index) continue; |
| 604 | 639 | const idx = global.outputSymtabIndex(elf_file) orelse continue; |
| 605 | 640 | const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); |
| 606 | 641 | elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file)); |
| ... | ... | @@ -611,10 +646,6 @@ pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void { |
| 611 | 646 | } |
| 612 | 647 | } |
| 613 | 648 | |
| 614 | | pub fn asFile(self: *ZigObject) File { |
| 615 | | return .{ .zig_object = self }; |
| 616 | | } |
| 617 | | |
| 618 | 649 | /// Returns atom's code. |
| 619 | 650 | /// Caller owns the memory. |
| 620 | 651 | pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 { |
| ... | ... | @@ -755,8 +786,8 @@ pub fn getOrCreateMetadataForLazySymbol( |
| 755 | 786 | }; |
| 756 | 787 | switch (metadata.state.*) { |
| 757 | 788 | .unused => { |
| 758 | | const symbol_index = try self.newAtom(elf_file); |
| 759 | | const sym = elf_file.symbol(symbol_index); |
| 789 | const symbol_index = try self.newSymbolWithAtom(gpa, 0); |
| 790 | const sym = self.symbol(symbol_index); |
| 760 | 791 | sym.flags.needs_zig_got = true; |
| 761 | 792 | metadata.symbol_index.* = symbol_index; |
| 762 | 793 | }, |
| ... | ... | @@ -817,10 +848,10 @@ pub fn getOrCreateMetadataForDecl( |
| 817 | 848 | const gop = try self.decls.getOrPut(gpa, decl_index); |
| 818 | 849 | if (!gop.found_existing) { |
| 819 | 850 | const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded; |
| 820 | | const symbol_index = try self.newAtom(elf_file); |
| 851 | const symbol_index = try self.newSymbolWithAtom(gpa, 0); |
| 821 | 852 | const mod = elf_file.base.comp.module.?; |
| 822 | 853 | const decl = mod.declPtr(decl_index); |
| 823 | | const sym = elf_file.symbol(symbol_index); |
| 854 | const sym = self.symbol(symbol_index); |
| 824 | 855 | if (decl.getOwnedVariable(mod)) |variable| { |
| 825 | 856 | if (variable.is_threadlocal and any_non_single_threaded) { |
| 826 | 857 | sym.flags.is_tls = true; |
| ... | ... | @@ -1064,7 +1095,7 @@ pub fn updateFunc( |
| 1064 | 1095 | |
| 1065 | 1096 | const sym_index = try self.getOrCreateMetadataForDecl(elf_file, decl_index); |
| 1066 | 1097 | self.freeUnnamedConsts(elf_file, decl_index); |
| 1067 | | elf_file.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file); |
| 1098 | self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file); |
| 1068 | 1099 | |
| 1069 | 1100 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 1070 | 1101 | defer code_buffer.deinit(); |
| ... | ... | @@ -1096,7 +1127,7 @@ pub fn updateFunc( |
| 1096 | 1127 | try self.updateDeclCode(elf_file, pt, decl_index, sym_index, shndx, code, elf.STT_FUNC); |
| 1097 | 1128 | |
| 1098 | 1129 | if (decl_state) |*ds| { |
| 1099 | | const sym = elf_file.symbol(sym_index); |
| 1130 | const sym = self.symbol(sym_index); |
| 1100 | 1131 | try self.dwarf.?.commitDeclState( |
| 1101 | 1132 | pt, |
| 1102 | 1133 | decl_index, |
| ... | ... | @@ -1130,13 +1161,13 @@ pub fn updateDecl( |
| 1130 | 1161 | const variable = decl.getOwnedVariable(mod).?; |
| 1131 | 1162 | const name = decl.name.toSlice(&mod.intern_pool); |
| 1132 | 1163 | const lib_name = variable.lib_name.toSlice(&mod.intern_pool); |
| 1133 | | const esym_index = try self.getGlobalSymbol(elf_file, name, lib_name); |
| 1134 | | elf_file.symbol(self.symbol(esym_index)).flags.needs_got = true; |
| 1164 | const sym_index = try self.getGlobalSymbol(elf_file, name, lib_name); |
| 1165 | self.symbol(sym_index).flags.needs_got = true; |
| 1135 | 1166 | return; |
| 1136 | 1167 | } |
| 1137 | 1168 | |
| 1138 | 1169 | const sym_index = try self.getOrCreateMetadataForDecl(elf_file, decl_index); |
| 1139 | | elf_file.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file); |
| 1170 | self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file); |
| 1140 | 1171 | |
| 1141 | 1172 | const gpa = elf_file.base.comp.gpa; |
| 1142 | 1173 | var code_buffer = std.ArrayList(u8).init(gpa); |
| ... | ... | @@ -1174,7 +1205,7 @@ pub fn updateDecl( |
| 1174 | 1205 | try self.updateDeclCode(elf_file, pt, decl_index, sym_index, shndx, code, elf.STT_OBJECT); |
| 1175 | 1206 | |
| 1176 | 1207 | if (decl_state) |*ds| { |
| 1177 | | const sym = elf_file.symbol(sym_index); |
| 1208 | const sym = self.symbol(sym_index); |
| 1178 | 1209 | try self.dwarf.?.commitDeclState( |
| 1179 | 1210 | pt, |
| 1180 | 1211 | decl_index, |
| ... | ... | @@ -1323,7 +1354,8 @@ fn lowerConst( |
| 1323 | 1354 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 1324 | 1355 | defer code_buffer.deinit(); |
| 1325 | 1356 | |
| 1326 | | const sym_index = try self.newAtom(elf_file); |
| 1357 | const name_off = try self.addString(gpa, name); |
| 1358 | const sym_index = try self.newSymbolWithAtom(gpa, name_off); |
| 1327 | 1359 | |
| 1328 | 1360 | const res = try codegen.generateSymbol( |
| 1329 | 1361 | &elf_file.base, |
| ... | ... | @@ -1339,27 +1371,19 @@ fn lowerConst( |
| 1339 | 1371 | .fail => |em| return .{ .fail = em }, |
| 1340 | 1372 | }; |
| 1341 | 1373 | |
| 1342 | | const local_sym = elf_file.symbol(sym_index); |
| 1343 | | const name_str_index = try self.strtab.insert(gpa, name); |
| 1344 | | local_sym.name_offset = name_str_index; |
| 1345 | | const local_esym = &self.local_esyms.items(.elf_sym)[local_sym.esym_index]; |
| 1346 | | local_esym.st_name = name_str_index; |
| 1374 | const local_sym = self.symbol(sym_index); |
| 1375 | const local_esym = local_sym.elfSym(elf_file); |
| 1347 | 1376 | local_esym.st_info |= elf.STT_OBJECT; |
| 1348 | 1377 | local_esym.st_size = code.len; |
| 1349 | 1378 | const atom_ptr = local_sym.atom(elf_file).?; |
| 1350 | 1379 | atom_ptr.alive = true; |
| 1351 | | atom_ptr.name_offset = name_str_index; |
| 1352 | 1380 | atom_ptr.alignment = required_alignment; |
| 1353 | 1381 | atom_ptr.size = code.len; |
| 1354 | 1382 | atom_ptr.output_section_index = output_section_index; |
| 1355 | 1383 | |
| 1356 | 1384 | try atom_ptr.allocate(elf_file); |
| 1357 | | // TODO rename and re-audit this method |
| 1358 | 1385 | errdefer self.freeDeclMetadata(elf_file, sym_index); |
| 1359 | 1386 | |
| 1360 | | local_sym.value = 0; |
| 1361 | | local_esym.st_value = 0; |
| 1362 | | |
| 1363 | 1387 | const shdr = elf_file.shdrs.items[output_section_index]; |
| 1364 | 1388 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); |
| 1365 | 1389 | try elf_file.base.file.?.pwriteAll(code, file_offset); |
| ... | ... | @@ -1401,9 +1425,9 @@ pub fn updateExports( |
| 1401 | 1425 | }, |
| 1402 | 1426 | }; |
| 1403 | 1427 | const sym_index = metadata.symbol_index; |
| 1404 | | const esym_index = elf_file.symbol(sym_index).esym_index; |
| 1405 | | const esym = self.local_esyms.items(.elf_sym)[esym_index]; |
| 1406 | | const esym_shndx = self.local_esyms.items(.shndx)[esym_index]; |
| 1428 | const esym_index = self.symbol(sym_index).esym_index; |
| 1429 | const esym = self.symtab.items(.elf_sym)[esym_index]; |
| 1430 | const esym_shndx = self.symtab.items(.shndx)[esym_index]; |
| 1407 | 1431 | |
| 1408 | 1432 | for (export_indices) |export_idx| { |
| 1409 | 1433 | const exp = mod.all_exports.items[export_idx]; |
| ... | ... | @@ -1437,22 +1461,27 @@ pub fn updateExports( |
| 1437 | 1461 | const stt_bits: u8 = @as(u4, @truncate(esym.st_info)); |
| 1438 | 1462 | const exp_name = exp.opts.name.toSlice(&mod.intern_pool); |
| 1439 | 1463 | const name_off = try self.strtab.insert(gpa, exp_name); |
| 1440 | | const global_esym_index = if (metadata.@"export"(self, exp_name)) |exp_index| |
| 1464 | const global_sym_index = if (metadata.@"export"(self, exp_name)) |exp_index| |
| 1441 | 1465 | exp_index.* |
| 1442 | 1466 | else blk: { |
| 1443 | | const global_esym_index = try self.getGlobalSymbol(elf_file, exp_name, null); |
| 1444 | | try metadata.exports.append(gpa, global_esym_index); |
| 1445 | | break :blk global_esym_index; |
| 1467 | const global_sym_index = try self.getGlobalSymbol(elf_file, exp_name, null); |
| 1468 | try metadata.exports.append(gpa, global_sym_index); |
| 1469 | break :blk global_sym_index; |
| 1446 | 1470 | }; |
| 1447 | 1471 | |
| 1448 | | const actual_esym_index = global_esym_index & symbol_mask; |
| 1449 | | const global_esym = &self.global_esyms.items(.elf_sym)[actual_esym_index]; |
| 1450 | | global_esym.st_value = @intCast(elf_file.symbol(sym_index).value); |
| 1472 | const value = self.symbol(sym_index).value; |
| 1473 | const global_sym = self.symbol(global_sym_index); |
| 1474 | global_sym.value = value; |
| 1475 | global_sym.flags.weak = exp.opts.linkage == .weak; |
| 1476 | global_sym.version_index = elf_file.default_version_index; |
| 1477 | global_sym.ref = .{ .index = esym_shndx, .file = self.index }; |
| 1478 | const global_esym = global_sym.elfSym(elf_file); |
| 1479 | global_esym.st_value = @intCast(value); |
| 1451 | 1480 | global_esym.st_shndx = esym.st_shndx; |
| 1452 | 1481 | global_esym.st_info = (stb_bits << 4) | stt_bits; |
| 1453 | 1482 | global_esym.st_name = name_off; |
| 1454 | 1483 | global_esym.st_size = esym.st_size; |
| 1455 | | self.global_esyms.items(.shndx)[actual_esym_index] = esym_shndx; |
| 1484 | self.symtab.items(.shndx)[global_sym.esym_index] = esym_shndx; |
| 1456 | 1485 | } |
| 1457 | 1486 | } |
| 1458 | 1487 | |
| ... | ... | @@ -1506,16 +1535,19 @@ pub fn getGlobalSymbol(self: *ZigObject, elf_file: *Elf, name: []const u8, lib_n |
| 1506 | 1535 | const off = try self.strtab.insert(gpa, name); |
| 1507 | 1536 | const lookup_gop = try self.globals_lookup.getOrPut(gpa, off); |
| 1508 | 1537 | if (!lookup_gop.found_existing) { |
| 1509 | | const esym_index = try self.addGlobalEsym(gpa); |
| 1510 | | const esym = self.elfSym(esym_index); |
| 1511 | | esym.st_name = off; |
| 1512 | | lookup_gop.value_ptr.* = esym_index; |
| 1513 | | const gop = try elf_file.getOrPutGlobal(name); |
| 1514 | | try self.global_symbols.append(gpa, gop.index); |
| 1538 | lookup_gop.value_ptr.* = try self.newSymbol(gpa, off); |
| 1515 | 1539 | } |
| 1516 | 1540 | return lookup_gop.value_ptr.*; |
| 1517 | 1541 | } |
| 1518 | 1542 | |
| 1543 | pub fn asFile(self: *ZigObject) File { |
| 1544 | return .{ .zig_object = self }; |
| 1545 | } |
| 1546 | |
| 1547 | fn addString(self: *ZigObject, allocator: Allocator, string: []const u8) !u32 { |
| 1548 | return self.strtab.insert(allocator, string); |
| 1549 | } |
| 1550 | |
| 1519 | 1551 | pub fn getString(self: ZigObject, off: u32) [:0]const u8 { |
| 1520 | 1552 | return self.strtab.getAssumeExists(off); |
| 1521 | 1553 | } |
| ... | ... | @@ -1586,6 +1618,73 @@ pub fn setAtomExtra(self: *ZigObject, index: u32, extra: Atom.Extra) void { |
| 1586 | 1618 | } |
| 1587 | 1619 | } |
| 1588 | 1620 | |
| 1621 | inline fn isGlobal(index: Symbol.Index) bool { |
| 1622 | return index & global_symbol_bit != 0; |
| 1623 | } |
| 1624 | |
| 1625 | pub fn symbol(self: *ZigObject, index: Symbol.Index) *Symbol { |
| 1626 | const actual_index = index & symbol_mask; |
| 1627 | if (isGlobal(index)) return &self.symbols.items[self.global_symbols.items[actual_index]]; |
| 1628 | return &self.symbols.items[self.local_symbols.items[actual_index]]; |
| 1629 | } |
| 1630 | |
| 1631 | pub fn resolveSymbol(self: ZigObject, index: Symbol.Index, elf_file: *Elf) Elf.Ref { |
| 1632 | if (isGlobal(index)) { |
| 1633 | const resolv = self.symbols_resolver.items[index & symbol_mask]; |
| 1634 | return elf_file.resolver.get(resolv).?; |
| 1635 | } |
| 1636 | return .{ .index = index, .file = self.index }; |
| 1637 | } |
| 1638 | |
| 1639 | pub fn addSymbol(self: *ZigObject, allocator: Allocator) !Symbol.Index { |
| 1640 | try self.symbols.ensureUnusedCapacity(allocator, 1); |
| 1641 | const index: Symbol.Index = @intCast(self.symbols.items.len); |
| 1642 | self.symbols.appendAssumeCapacity(.{ .file_index = self.index }); |
| 1643 | return index; |
| 1644 | } |
| 1645 | |
| 1646 | pub fn addSymbolExtra(self: *ZigObject, allocator: Allocator, extra: Symbol.Extra) !u32 { |
| 1647 | const fields = @typeInfo(Symbol.Extra).Struct.fields; |
| 1648 | try self.symbols_extra.ensureUnusedCapacity(allocator, fields.len); |
| 1649 | return self.addSymbolExtraAssumeCapacity(extra); |
| 1650 | } |
| 1651 | |
| 1652 | pub fn addSymbolExtraAssumeCapacity(self: *ZigObject, extra: Symbol.Extra) u32 { |
| 1653 | const index = @as(u32, @intCast(self.symbols_extra.items.len)); |
| 1654 | const fields = @typeInfo(Symbol.Extra).Struct.fields; |
| 1655 | inline for (fields) |field| { |
| 1656 | self.symbols_extra.appendAssumeCapacity(switch (field.type) { |
| 1657 | u32 => @field(extra, field.name), |
| 1658 | else => @compileError("bad field type"), |
| 1659 | }); |
| 1660 | } |
| 1661 | return index; |
| 1662 | } |
| 1663 | |
| 1664 | pub fn symbolExtra(self: *ZigObject, index: u32) Symbol.Extra { |
| 1665 | const fields = @typeInfo(Symbol.Extra).Struct.fields; |
| 1666 | var i: usize = index; |
| 1667 | var result: Symbol.Extra = undefined; |
| 1668 | inline for (fields) |field| { |
| 1669 | @field(result, field.name) = switch (field.type) { |
| 1670 | u32 => self.symbols_extra.items[i], |
| 1671 | else => @compileError("bad field type"), |
| 1672 | }; |
| 1673 | i += 1; |
| 1674 | } |
| 1675 | return result; |
| 1676 | } |
| 1677 | |
| 1678 | pub fn setSymbolExtra(self: *ZigObject, index: u32, extra: Symbol.Extra) void { |
| 1679 | const fields = @typeInfo(Symbol.Extra).Struct.fields; |
| 1680 | inline for (fields, 0..) |field, i| { |
| 1681 | self.symbols_extra.items[index + i] = switch (field.type) { |
| 1682 | u32 => @field(extra, field.name), |
| 1683 | else => @compileError("bad field type"), |
| 1684 | }; |
| 1685 | } |
| 1686 | } |
| 1687 | |
| 1589 | 1688 | pub fn fmtSymtab(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(formatSymtab) { |
| 1590 | 1689 | return .{ .data = .{ |
| 1591 | 1690 | .self = self, |
| ... | ... | @@ -1658,9 +1757,9 @@ const DeclMetadata = struct { |
| 1658 | 1757 | /// A list of all exports aliases of this Decl. |
| 1659 | 1758 | exports: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 1660 | 1759 | |
| 1661 | | fn @"export"(m: DeclMetadata, zig_object: *ZigObject, name: []const u8) ?*u32 { |
| 1760 | fn @"export"(m: DeclMetadata, zo: *ZigObject, name: []const u8) ?*u32 { |
| 1662 | 1761 | for (m.exports.items) |*exp| { |
| 1663 | | const exp_name = zig_object.getString(zig_object.elfSym(exp.*).st_name); |
| 1762 | const exp_name = zo.getString(zo.symbol(exp.*).name_off); |
| 1664 | 1763 | if (mem.eql(u8, name, exp_name)) return exp; |
| 1665 | 1764 | } |
| 1666 | 1765 | return null; |