authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-30 14:58:59+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-30 19:09:13+01:00
logb2e847a41a817a78b5aa3a8f1e0afa5a33ad9194
treef248f9cdbc1c5f320d07aa19318e81f9a5fef446
parent10d03acdb5ff81c112280854629c9f9032e14330

elf: rename ZigModule to ZigObject


9 files changed, 493 insertions(+), 502 deletions(-)

CMakeLists.txt+1-1
......@@ -594,7 +594,7 @@ set(ZIG_STAGE2_SOURCES
594594 "${CMAKE_SOURCE_DIR}/src/link/Elf/Object.zig"
595595 "${CMAKE_SOURCE_DIR}/src/link/Elf/SharedObject.zig"
596596 "${CMAKE_SOURCE_DIR}/src/link/Elf/Symbol.zig"
597 "${CMAKE_SOURCE_DIR}/src/link/Elf/ZigModule.zig"
597 "${CMAKE_SOURCE_DIR}/src/link/Elf/ZigObject.zig"
598598 "${CMAKE_SOURCE_DIR}/src/link/Elf/eh_frame.zig"
599599 "${CMAKE_SOURCE_DIR}/src/link/Elf/file.zig"
600600 "${CMAKE_SOURCE_DIR}/src/link/Elf/gc.zig"
src/arch/x86_64/Emit.zig+1-1
......@@ -86,7 +86,7 @@ pub fn emitMir(emit: *Emit) Error!void {
8686 }),
8787 .linker_reloc => |data| if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| {
8888 const atom = elf_file.symbol(data.atom_index).atom(elf_file).?;
89 const sym = elf_file.symbol(elf_file.zigModulePtr().symbol(data.sym_index));
89 const sym = elf_file.symbol(elf_file.zigObjectPtr().?.symbol(data.sym_index));
9090 if (emit.lower.bin_file.options.pic) {
9191 const r_type: u32 = if (sym.flags.has_zig_got)
9292 link.File.Elf.R_X86_64_ZIG_GOTPCREL
src/codegen.zig+1-1
......@@ -904,7 +904,7 @@ fn genDeclRef(
904904 else
905905 null;
906906 const sym_index = try elf_file.getGlobalSymbol(name, lib_name);
907 elf_file.symbol(elf_file.zigModulePtr().symbol(sym_index)).flags.needs_got = true;
907 elf_file.symbol(elf_file.zigObjectPtr().?.symbol(sym_index)).flags.needs_got = true;
908908 return GenResult.mcv(.{ .load_symbol = sym_index });
909909 }
910910 const sym_index = try elf_file.getOrCreateMetadataForDecl(decl_index);
src/link/Elf.zig+87-95
......@@ -11,7 +11,7 @@ llvm_object: ?*LlvmObject = null,
1111/// Index of each input file also encodes the priority or precedence of one input file
1212/// over another.
1313files: std.MultiArrayList(File.Entry) = .{},
14zig_module_index: ?File.Index = null,
14zig_object_index: ?File.Index = null,
1515linker_defined_index: ?File.Index = null,
1616objects: std.ArrayListUnmanaged(File.Index) = .{},
1717shared_objects: std.ArrayListUnmanaged(File.Index) = .{},
......@@ -327,24 +327,24 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
327327 }
328328
329329 const index = @as(File.Index, @intCast(try self.files.addOne(allocator)));
330 self.files.set(index, .{ .zig_module = .{
330 self.files.set(index, .{ .zig_object = .{
331331 .index = index,
332332 .path = options.module.?.main_mod.root_src_path,
333333 } });
334 self.zig_module_index = index;
335 const zig_module = self.file(index).?.zig_module;
334 self.zig_object_index = index;
335 const zig_object = self.zigObjectPtr().?;
336336
337 try zig_module.atoms.append(allocator, 0); // null input section
337 try zig_object.atoms.append(allocator, 0); // null input section
338338
339339 const name_off = try self.strtab.insert(allocator, std.fs.path.stem(options.module.?.main_mod.root_src_path));
340340 const symbol_index = try self.addSymbol();
341 try zig_module.local_symbols.append(allocator, symbol_index);
341 try zig_object.local_symbols.append(allocator, symbol_index);
342342 const symbol_ptr = self.symbol(symbol_index);
343 symbol_ptr.file_index = zig_module.index;
343 symbol_ptr.file_index = zig_object.index;
344344 symbol_ptr.name_offset = name_off;
345345
346 const esym_index = try zig_module.addLocalEsym(allocator);
347 const esym = &zig_module.local_esyms.items(.elf_sym)[esym_index];
346 const esym_index = try zig_object.addLocalEsym(allocator);
347 const esym = &zig_object.local_esyms.items(.elf_sym)[esym_index];
348348 esym.st_name = name_off;
349349 esym.st_info |= elf.STT_FILE;
350350 esym.st_shndx = elf.SHN_ABS;
......@@ -401,7 +401,7 @@ pub fn deinit(self: *Elf) void {
401401
402402 for (self.files.items(.tags), self.files.items(.data)) |tag, *data| switch (tag) {
403403 .null => {},
404 .zig_module => data.zig_module.deinit(gpa),
404 .zig_object => data.zig_object.deinit(gpa),
405405 .linker_defined => data.linker_defined.deinit(gpa),
406406 .object => data.object.deinit(gpa),
407407 .shared_object => data.shared_object.deinit(gpa),
......@@ -726,7 +726,7 @@ fn allocateNonAllocSection(self: *Elf, opts: AllocateNonAllocSectionOpts) error{
726726 return index;
727727}
728728
729/// TODO move to ZigModule
729/// TODO move to ZigObject
730730pub fn initMetadata(self: *Elf) !void {
731731 const gpa = self.base.allocator;
732732 const ptr_size = self.ptrWidthBytes();
......@@ -1041,7 +1041,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
10411041 } else null;
10421042 const gc_sections = self.base.options.gc_sections orelse false;
10431043
1044 if (self.base.options.output_mode == .Obj and self.zig_module_index == null) {
1044 if (self.base.options.output_mode == .Obj and self.zig_object_index == null) {
10451045 // TODO this will become -r route I guess. For now, just copy the object file.
10461046 assert(self.base.file == null); // TODO uncomment once we implement -r
10471047 const the_object_path = blk: {
......@@ -1543,7 +1543,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
15431543 }
15441544
15451545 // Now, we are ready to resolve the symbols across all input files.
1546 // We will first resolve the files in the ZigModule, next in the parsed
1546 // We will first resolve the files in the ZigObject, next in the parsed
15471547 // input Object files.
15481548 // Any qualifing unresolved symbol will be upgraded to an absolute, weak
15491549 // symbol for potential resolution at load-time.
......@@ -1576,7 +1576,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
15761576 // Scan and create missing synthetic entries such as GOT indirection.
15771577 try self.scanRelocs();
15781578
1579 // TODO I need to re-think how to handle ZigModule's debug sections AND debug sections
1579 // TODO I need to re-think how to handle ZigObject's debug sections AND debug sections
15801580 // extracted from input object files correctly.
15811581 if (self.dwarf) |*dw| {
15821582 if (self.debug_abbrev_section_dirty) {
......@@ -1645,15 +1645,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
16451645
16461646 // Beyond this point, everything has been allocated a virtual address and we can resolve
16471647 // the relocations, and commit objects to file.
1648 if (self.zig_module_index) |index| {
1649 const zig_module = self.file(index).?.zig_module;
1650 for (zig_module.atoms.items) |atom_index| {
1648 if (self.zigObjectPtr()) |zig_object| {
1649 for (zig_object.atoms.items) |atom_index| {
16511650 const atom_ptr = self.atom(atom_index) orelse continue;
16521651 if (!atom_ptr.flags.alive) continue;
16531652 const out_shndx = atom_ptr.outputShndx() orelse continue;
16541653 const shdr = &self.shdrs.items[out_shndx];
16551654 if (shdr.sh_type == elf.SHT_NOBITS) continue;
1656 const code = try zig_module.codeAlloc(self, atom_index);
1655 const code = try zig_object.codeAlloc(self, atom_index);
16571656 defer gpa.free(code);
16581657 const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr;
16591658 atom_ptr.resolveRelocsAlloc(self, code) catch |err| switch (err) {
......@@ -1926,8 +1925,8 @@ fn accessLibPath(
19261925/// 5. Remove references to dead objects/shared objects
19271926/// 6. Re-run symbol resolution on pruned objects and shared objects sets.
19281927fn resolveSymbols(self: *Elf) void {
1929 // Resolve symbols in the ZigModule. For now, we assume that it's always live.
1930 if (self.zig_module_index) |index| self.file(index).?.resolveSymbols(self);
1928 // Resolve symbols in the ZigObject. For now, we assume that it's always live.
1929 if (self.zigObjectPtr()) |zig_object| zig_object.resolveSymbols(self);
19311930 // Resolve symbols on the set of all objects and shared objects (even if some are unneeded).
19321931 for (self.objects.items) |index| self.file(index).?.resolveSymbols(self);
19331932 for (self.shared_objects.items) |index| self.file(index).?.resolveSymbols(self);
......@@ -1936,7 +1935,7 @@ fn resolveSymbols(self: *Elf) void {
19361935 self.markLive();
19371936
19381937 // Reset state of all globals after marking live objects.
1939 if (self.zig_module_index) |index| self.file(index).?.resetGlobals(self);
1938 if (self.zigObjectPtr()) |zig_object| zig_object.resetGlobals(self);
19401939 for (self.objects.items) |index| self.file(index).?.resetGlobals(self);
19411940 for (self.shared_objects.items) |index| self.file(index).?.resetGlobals(self);
19421941
......@@ -1988,7 +1987,7 @@ fn resolveSymbols(self: *Elf) void {
19881987 }
19891988
19901989 // Re-resolve the symbols.
1991 if (self.zig_module_index) |index| self.file(index).?.resolveSymbols(self);
1990 if (self.zigObjectPtr()) |zig_object| zig_object.resolveSymbols(self);
19921991 for (self.objects.items) |index| self.file(index).?.resolveSymbols(self);
19931992 for (self.shared_objects.items) |index| self.file(index).?.resolveSymbols(self);
19941993}
......@@ -1998,7 +1997,7 @@ fn resolveSymbols(self: *Elf) void {
19981997/// This routine will prune unneeded objects extracted from archives and
19991998/// unneeded shared objects.
20001999fn markLive(self: *Elf) void {
2001 if (self.zig_module_index) |index| self.file(index).?.markLive(self);
2000 if (self.zigObjectPtr()) |zig_object| zig_object.markLive(self);
20022001 for (self.objects.items) |index| {
20032002 const file_ptr = self.file(index).?;
20042003 if (file_ptr.isAlive()) file_ptr.markLive(self);
......@@ -2057,7 +2056,7 @@ fn markImportsExports(self: *Elf) void {
20572056 }
20582057 }
20592058
2060 if (self.zig_module_index) |index| {
2059 if (self.zig_object_index) |index| {
20612060 mark(self, index);
20622061 }
20632062
......@@ -2067,9 +2066,8 @@ fn markImportsExports(self: *Elf) void {
20672066}
20682067
20692068fn claimUnresolved(self: *Elf) void {
2070 if (self.zig_module_index) |index| {
2071 const zig_module = self.file(index).?.zig_module;
2072 zig_module.claimUnresolved(self);
2069 if (self.zigObjectPtr()) |zig_object| {
2070 zig_object.claimUnresolved(self);
20732071 }
20742072 for (self.objects.items) |index| {
20752073 const object = self.file(index).?.object;
......@@ -2093,9 +2091,8 @@ fn scanRelocs(self: *Elf) !void {
20932091 undefs.deinit();
20942092 }
20952093
2096 if (self.zig_module_index) |index| {
2097 const zig_module = self.file(index).?.zig_module;
2098 try zig_module.scanRelocs(self, &undefs);
2094 if (self.zigObjectPtr()) |zig_object| {
2095 try zig_object.scanRelocs(self, &undefs);
20992096 }
21002097 for (self.objects.items) |index| {
21012098 const object = self.file(index).?.object;
......@@ -3114,9 +3111,9 @@ pub fn getOrCreateMetadataForLazySymbol(self: *Elf, lazy_sym: link.File.LazySymb
31143111 .state = &gop.value_ptr.rodata_state,
31153112 },
31163113 };
3117 const zig_module = self.file(self.zig_module_index.?).?.zig_module;
3114 const zig_object = self.zigObjectPtr().?;
31183115 switch (metadata.state.*) {
3119 .unused => metadata.symbol_index.* = try zig_module.addAtom(self),
3116 .unused => metadata.symbol_index.* = try zig_object.addAtom(self),
31203117 .pending_flush => return metadata.symbol_index.*,
31213118 .flushed => {},
31223119 }
......@@ -3130,8 +3127,8 @@ pub fn getOrCreateMetadataForLazySymbol(self: *Elf, lazy_sym: link.File.LazySymb
31303127pub fn getOrCreateMetadataForDecl(self: *Elf, decl_index: Module.Decl.Index) !Symbol.Index {
31313128 const gop = try self.decls.getOrPut(self.base.allocator, decl_index);
31323129 if (!gop.found_existing) {
3133 const zig_module = self.file(self.zig_module_index.?).?.zig_module;
3134 gop.value_ptr.* = .{ .symbol_index = try zig_module.addAtom(self) };
3130 const zig_object = self.zigObjectPtr().?;
3131 gop.value_ptr.* = .{ .symbol_index = try zig_object.addAtom(self) };
31353132 }
31363133 return gop.value_ptr.symbol_index;
31373134}
......@@ -3173,7 +3170,7 @@ fn updateDeclCode(
31733170) !void {
31743171 const gpa = self.base.allocator;
31753172 const mod = self.base.options.module.?;
3176 const zig_module = self.file(self.zig_module_index.?).?.zig_module;
3173 const zig_object = self.zigObjectPtr().?;
31773174 const decl = mod.declPtr(decl_index);
31783175
31793176 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
......@@ -3182,7 +3179,7 @@ fn updateDeclCode(
31823179 const required_alignment = decl.getAlignment(mod);
31833180
31843181 const sym = self.symbol(sym_index);
3185 const esym = &zig_module.local_esyms.items(.elf_sym)[sym.esym_index];
3182 const esym = &zig_object.local_esyms.items(.elf_sym)[sym.esym_index];
31863183 const atom_ptr = sym.atom(self).?;
31873184
31883185 const shdr_index = self.getDeclShdrIndex(decl_index, code);
......@@ -3340,7 +3337,7 @@ pub fn updateDecl(
33403337 const name = mod.intern_pool.stringToSlice(decl.name);
33413338 const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name);
33423339 const esym_index = try self.getGlobalSymbol(name, lib_name);
3343 self.symbol(self.zigModulePtr().symbol(esym_index)).flags.needs_got = true;
3340 self.symbol(self.zigObjectPtr().?.symbol(esym_index)).flags.needs_got = true;
33443341 return;
33453342 }
33463343
......@@ -3401,7 +3398,7 @@ pub fn updateDecl(
34013398fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol.Index) !void {
34023399 const gpa = self.base.allocator;
34033400 const mod = self.base.options.module.?;
3404 const zig_module = self.file(self.zig_module_index.?).?.zig_module;
3401 const zig_object = self.zigObjectPtr().?;
34053402
34063403 var required_alignment: InternPool.Alignment = .none;
34073404 var code_buffer = std.ArrayList(u8).init(gpa);
......@@ -3449,7 +3446,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol.
34493446 const phdr_index = self.phdr_to_shdr_table.get(output_section_index).?;
34503447 local_sym.name_offset = name_str_index;
34513448 local_sym.output_section_index = output_section_index;
3452 const local_esym = &zig_module.local_esyms.items(.elf_sym)[local_sym.esym_index];
3449 const local_esym = &zig_object.local_esyms.items(.elf_sym)[local_sym.esym_index];
34533450 local_esym.st_name = name_str_index;
34543451 local_esym.st_info |= elf.STT_OBJECT;
34553452 local_esym.st_size = code.len;
......@@ -3519,8 +3516,8 @@ fn lowerConst(
35193516 var code_buffer = std.ArrayList(u8).init(gpa);
35203517 defer code_buffer.deinit();
35213518
3522 const zig_module = self.file(self.zig_module_index.?).?.zig_module;
3523 const sym_index = try zig_module.addAtom(self);
3519 const zig_object = self.zigObjectPtr().?;
3520 const sym_index = try zig_object.addAtom(self);
35243521
35253522 const res = try codegen.generateSymbol(&self.base, src_loc, tv, &code_buffer, .{
35263523 .none = {},
......@@ -3537,7 +3534,7 @@ fn lowerConst(
35373534 const name_str_index = try self.strtab.insert(gpa, name);
35383535 local_sym.name_offset = name_str_index;
35393536 local_sym.output_section_index = output_section_index;
3540 const local_esym = &zig_module.local_esyms.items(.elf_sym)[local_sym.esym_index];
3537 const local_esym = &zig_object.local_esyms.items(.elf_sym)[local_sym.esym_index];
35413538 local_esym.st_name = name_str_index;
35423539 local_esym.st_info |= elf.STT_OBJECT;
35433540 local_esym.st_size = code.len;
......@@ -3579,7 +3576,7 @@ pub fn updateExports(
35793576 defer tracy.end();
35803577
35813578 const gpa = self.base.allocator;
3582 const zig_module = self.file(self.zig_module_index.?).?.zig_module;
3579 const zig_object = self.zigObjectPtr().?;
35833580 const metadata = switch (exported) {
35843581 .decl_index => |decl_index| blk: {
35853582 _ = try self.getOrCreateMetadataForDecl(decl_index);
......@@ -3603,8 +3600,8 @@ pub fn updateExports(
36033600 };
36043601 const sym_index = metadata.symbol_index;
36053602 const esym_index = self.symbol(sym_index).esym_index;
3606 const esym = zig_module.local_esyms.items(.elf_sym)[esym_index];
3607 const esym_shndx = zig_module.local_esyms.items(.shndx)[esym_index];
3603 const esym = zig_object.local_esyms.items(.elf_sym)[esym_index];
3604 const esym_shndx = zig_object.local_esyms.items(.shndx)[esym_index];
36083605
36093606 for (exports) |exp| {
36103607 if (exp.opts.section.unwrap()) |section_name| {
......@@ -3638,24 +3635,24 @@ pub fn updateExports(
36383635 const exp_name = mod.intern_pool.stringToSlice(exp.opts.name);
36393636 const name_off = try self.strtab.insert(gpa, exp_name);
36403637 const global_esym_index = if (metadata.@"export"(self, exp_name)) |exp_index| exp_index.* else blk: {
3641 const global_esym_index = try zig_module.addGlobalEsym(gpa);
3642 const lookup_gop = try zig_module.globals_lookup.getOrPut(gpa, name_off);
3643 const global_esym = zig_module.elfSym(global_esym_index);
3638 const global_esym_index = try zig_object.addGlobalEsym(gpa);
3639 const lookup_gop = try zig_object.globals_lookup.getOrPut(gpa, name_off);
3640 const global_esym = zig_object.elfSym(global_esym_index);
36443641 global_esym.st_name = name_off;
36453642 lookup_gop.value_ptr.* = global_esym_index;
36463643 try metadata.exports.append(gpa, global_esym_index);
36473644 const gop = try self.getOrPutGlobal(name_off);
3648 try zig_module.global_symbols.append(gpa, gop.index);
3645 try zig_object.global_symbols.append(gpa, gop.index);
36493646 break :blk global_esym_index;
36503647 };
36513648
3652 const actual_esym_index = global_esym_index & ZigModule.symbol_mask;
3653 const global_esym = &zig_module.global_esyms.items(.elf_sym)[actual_esym_index];
3649 const actual_esym_index = global_esym_index & ZigObject.symbol_mask;
3650 const global_esym = &zig_object.global_esyms.items(.elf_sym)[actual_esym_index];
36543651 global_esym.st_value = self.symbol(sym_index).value;
36553652 global_esym.st_shndx = esym.st_shndx;
36563653 global_esym.st_info = (stb_bits << 4) | stt_bits;
36573654 global_esym.st_name = name_off;
3658 zig_module.global_esyms.items(.shndx)[actual_esym_index] = esym_shndx;
3655 zig_object.global_esyms.items(.shndx)[actual_esym_index] = esym_shndx;
36593656 }
36603657}
36613658
......@@ -3683,20 +3680,20 @@ pub fn deleteDeclExport(
36833680 if (self.llvm_object) |_| return;
36843681 const metadata = self.decls.getPtr(decl_index) orelse return;
36853682 const mod = self.base.options.module.?;
3686 const zig_module = self.file(self.zig_module_index.?).?.zig_module;
3683 const zig_object = self.zigObjectPtr().?;
36873684 const exp_name = mod.intern_pool.stringToSlice(name);
36883685 const esym_index = metadata.@"export"(self, exp_name) orelse return;
36893686 log.debug("deleting export '{s}'", .{exp_name});
3690 const esym = &zig_module.global_esyms.items(.elf_sym)[esym_index.*];
3691 _ = zig_module.globals_lookup.remove(esym.st_name);
3687 const esym = &zig_object.global_esyms.items(.elf_sym)[esym_index.*];
3688 _ = zig_object.globals_lookup.remove(esym.st_name);
36923689 const sym_index = self.resolver.get(esym.st_name).?;
36933690 const sym = self.symbol(sym_index);
3694 if (sym.file_index == zig_module.index) {
3691 if (sym.file_index == zig_object.index) {
36953692 _ = self.resolver.swapRemove(esym.st_name);
36963693 sym.* = .{};
36973694 }
36983695 esym.* = null_sym;
3699 zig_module.global_esyms.items(.shndx)[esym_index.*] = elf.SHN_UNDEF;
3696 zig_object.global_esyms.items(.shndx)[esym_index.*] = elf.SHN_UNDEF;
37003697}
37013698
37023699fn addLinkerDefinedSymbols(self: *Elf) !void {
......@@ -3917,8 +3914,8 @@ fn initSections(self: *Elf) !void {
39173914 const needs_rela_dyn = blk: {
39183915 if (self.got.flags.needs_rela or self.got.flags.needs_tlsld or
39193916 self.zig_got.flags.needs_rela or self.copy_rel.symbols.items.len > 0) break :blk true;
3920 if (self.zig_module_index) |index| {
3921 if (self.file(index).?.zig_module.num_dynrelocs > 0) break :blk true;
3917 if (self.zigObjectPtr()) |zig_object| {
3918 if (zig_object.num_dynrelocs > 0) break :blk true;
39223919 }
39233920 for (self.objects.items) |index| {
39243921 if (self.file(index).?.object.num_dynrelocs > 0) break :blk true;
......@@ -4512,16 +4509,15 @@ fn sortShdrs(self: *Elf) !void {
45124509 }
45134510 }
45144511
4515 if (self.zig_module_index) |index| {
4516 const zig_module = self.file(index).?.zig_module;
4517 for (zig_module.atoms.items) |atom_index| {
4512 if (self.zigObjectPtr()) |zig_object| {
4513 for (zig_object.atoms.items) |atom_index| {
45184514 const atom_ptr = self.atom(atom_index) orelse continue;
45194515 if (!atom_ptr.flags.alive) continue;
45204516 const out_shndx = atom_ptr.outputShndx() orelse continue;
45214517 atom_ptr.output_section_index = backlinks[out_shndx];
45224518 }
45234519
4524 for (zig_module.locals()) |local_index| {
4520 for (zig_object.locals()) |local_index| {
45254521 const local = self.symbol(local_index);
45264522 const atom_ptr = local.atom(self) orelse continue;
45274523 if (!atom_ptr.flags.alive) continue;
......@@ -4529,11 +4525,11 @@ fn sortShdrs(self: *Elf) !void {
45294525 local.output_section_index = backlinks[out_shndx];
45304526 }
45314527
4532 for (zig_module.globals()) |global_index| {
4528 for (zig_object.globals()) |global_index| {
45334529 const global = self.symbol(global_index);
45344530 const atom_ptr = global.atom(self) orelse continue;
45354531 if (!atom_ptr.flags.alive) continue;
4536 if (global.file(self).?.index() != index) continue;
4532 if (global.file(self).?.index() != zig_object.index) continue;
45374533 const out_shndx = global.outputShndx() orelse continue;
45384534 global.output_section_index = backlinks[out_shndx];
45394535 }
......@@ -4599,8 +4595,8 @@ fn updateSectionSizes(self: *Elf) !void {
45994595
46004596 if (self.rela_dyn_section_index) |shndx| {
46014597 var num = self.got.numRela(self) + self.copy_rel.numRela() + self.zig_got.numRela();
4602 if (self.zig_module_index) |index| {
4603 num += self.file(index).?.zig_module.num_dynrelocs;
4598 if (self.zigObjectPtr()) |zig_object| {
4599 num += zig_object.num_dynrelocs;
46044600 }
46054601 for (self.objects.items) |index| {
46064602 num += self.file(index).?.object.num_dynrelocs;
......@@ -5079,11 +5075,10 @@ fn writeAtoms(self: *Elf) !void {
50795075fn updateSymtabSize(self: *Elf) !void {
50805076 var sizes = SymtabSize{};
50815077
5082 if (self.zig_module_index) |index| {
5083 const zig_module = self.file(index).?.zig_module;
5084 zig_module.updateSymtabSize(self);
5085 sizes.nlocals += zig_module.output_symtab_size.nlocals;
5086 sizes.nglobals += zig_module.output_symtab_size.nglobals;
5078 if (self.zigObjectPtr()) |zig_object| {
5079 zig_object.updateSymtabSize(self);
5080 sizes.nlocals += zig_object.output_symtab_size.nlocals;
5081 sizes.nglobals += zig_object.output_symtab_size.nglobals;
50875082 }
50885083
50895084 for (self.objects.items) |index| {
......@@ -5299,11 +5294,10 @@ fn writeSymtab(self: *Elf) !void {
52995294 .symtab = symtab,
53005295 };
53015296
5302 if (self.zig_module_index) |index| {
5303 const zig_module = self.file(index).?.zig_module;
5304 zig_module.writeSymtab(self, ctx);
5305 ctx.ilocal += zig_module.output_symtab_size.nlocals;
5306 ctx.iglobal += zig_module.output_symtab_size.nglobals;
5297 if (self.zigObjectPtr()) |zig_object| {
5298 zig_object.writeSymtab(self, ctx);
5299 ctx.ilocal += zig_object.output_symtab_size.nlocals;
5300 ctx.iglobal += zig_object.output_symtab_size.nglobals;
53075301 }
53085302
53095303 for (self.objects.items) |index| {
......@@ -5863,7 +5857,7 @@ pub fn file(self: *Elf, index: File.Index) ?File {
58635857 return switch (tag) {
58645858 .null => null,
58655859 .linker_defined => .{ .linker_defined = &self.files.items(.data)[index].linker_defined },
5866 .zig_module => .{ .zig_module = &self.files.items(.data)[index].zig_module },
5860 .zig_object => .{ .zig_object = &self.files.items(.data)[index].zig_object },
58675861 .object => .{ .object = &self.files.items(.data)[index].object },
58685862 .shared_object => .{ .shared_object = &self.files.items(.data)[index].shared_object },
58695863 };
......@@ -5964,23 +5958,22 @@ pub fn getGlobalSymbol(self: *Elf, name: []const u8, lib_name: ?[]const u8) !u32
59645958 _ = lib_name;
59655959 const gpa = self.base.allocator;
59665960 const off = try self.strtab.insert(gpa, name);
5967 const zig_module = self.file(self.zig_module_index.?).?.zig_module;
5968 const lookup_gop = try zig_module.globals_lookup.getOrPut(gpa, off);
5961 const zig_object = self.zigObjectPtr().?;
5962 const lookup_gop = try zig_object.globals_lookup.getOrPut(gpa, off);
59695963 if (!lookup_gop.found_existing) {
5970 const esym_index = try zig_module.addGlobalEsym(gpa);
5971 const esym = zig_module.elfSym(esym_index);
5964 const esym_index = try zig_object.addGlobalEsym(gpa);
5965 const esym = zig_object.elfSym(esym_index);
59725966 esym.st_name = off;
59735967 lookup_gop.value_ptr.* = esym_index;
59745968 const gop = try self.getOrPutGlobal(off);
5975 try zig_module.global_symbols.append(gpa, gop.index);
5969 try zig_object.global_symbols.append(gpa, gop.index);
59765970 }
59775971 return lookup_gop.value_ptr.*;
59785972}
59795973
5980pub fn zigModulePtr(self: *Elf) *ZigModule {
5981 assert(self.zig_module_index != null);
5982 const file_ptr = self.file(self.zig_module_index.?).?;
5983 return file_ptr.zig_module;
5974pub fn zigObjectPtr(self: *Elf) ?*ZigObject {
5975 const index = self.zig_object_index orelse return null;
5976 return self.file(index).?.zig_object;
59845977}
59855978
59865979const GetOrCreateComdatGroupOwnerResult = struct {
......@@ -6245,12 +6238,11 @@ fn fmtDumpState(
62456238 _ = unused_fmt_string;
62466239 _ = options;
62476240
6248 if (self.zig_module_index) |index| {
6249 const zig_module = self.file(index).?.zig_module;
6250 try writer.print("zig_module({d}) : {s}\n", .{ index, zig_module.path });
6241 if (self.zigObjectPtr()) |zig_object| {
6242 try writer.print("zig_object({d}) : {s}\n", .{ zig_object.index, zig_object.path });
62516243 try writer.print("{}{}\n", .{
6252 zig_module.fmtAtoms(self),
6253 zig_module.fmtSymtab(self),
6244 zig_object.fmtAtoms(self),
6245 zig_object.fmtSymtab(self),
62546246 });
62556247 }
62566248
......@@ -6379,9 +6371,9 @@ const DeclMetadata = struct {
63796371 exports: std.ArrayListUnmanaged(Symbol.Index) = .{},
63806372
63816373 fn @"export"(m: DeclMetadata, elf_file: *Elf, name: []const u8) ?*u32 {
6382 const zig_module = elf_file.file(elf_file.zig_module_index.?).?.zig_module;
6374 const zig_object = elf_file.zigObjectPtr().?;
63836375 for (m.exports.items) |*exp| {
6384 const exp_name = elf_file.strtab.getAssumeExists(zig_module.elfSym(exp.*).st_name);
6376 const exp_name = elf_file.strtab.getAssumeExists(zig_object.elfSym(exp.*).st_name);
63856377 if (mem.eql(u8, name, exp_name)) return exp;
63866378 }
63876379 return null;
......@@ -6491,4 +6483,4 @@ const TypedValue = @import("../TypedValue.zig");
64916483const Value = @import("../value.zig").Value;
64926484const VerneedSection = synthetic_sections.VerneedSection;
64936485const ZigGotSection = synthetic_sections.ZigGotSection;
6494const ZigModule = @import("Elf/ZigModule.zig");
6486const ZigObject = @import("Elf/ZigObject.zig");
src/link/Elf/Atom.zig+14-14
......@@ -52,7 +52,7 @@ pub fn file(self: Atom, elf_file: *Elf) ?File {
5252pub fn inputShdr(self: Atom, elf_file: *Elf) Object.ElfShdr {
5353 return switch (self.file(elf_file).?) {
5454 .object => |x| x.shdrs.items[self.input_section_index],
55 .zig_module => |x| x.inputShdr(self.atom_index, elf_file),
55 .zig_object => |x| x.inputShdr(self.atom_index, elf_file),
5656 else => unreachable,
5757 };
5858}
......@@ -270,14 +270,14 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
270270 // TODO create relocs free list
271271 self.freeRelocs(elf_file);
272272 // TODO figure out how to free input section mappind in ZigModule
273 // const zig_module = self.file(elf_file).?.zig_module;
274 // assert(zig_module.atoms.swapRemove(self.atom_index));
273 // const zig_object = elf_file.zigObjectPtr().?
274 // assert(zig_object.atoms.swapRemove(self.atom_index));
275275 self.* = .{};
276276}
277277
278278pub fn relocs(self: Atom, elf_file: *Elf) []align(1) const elf.Elf64_Rela {
279279 return switch (self.file(elf_file).?) {
280 .zig_module => |x| x.relocs.items[self.relocs_section_index].items,
280 .zig_object => |x| x.relocs.items[self.relocs_section_index].items,
281281 .object => |x| x.getRelocs(self.relocs_section_index),
282282 else => unreachable,
283283 };
......@@ -298,17 +298,17 @@ pub fn markFdesDead(self: Atom, elf_file: *Elf) void {
298298pub fn addReloc(self: Atom, elf_file: *Elf, reloc: elf.Elf64_Rela) !void {
299299 const gpa = elf_file.base.allocator;
300300 const file_ptr = self.file(elf_file).?;
301 assert(file_ptr == .zig_module);
302 const zig_module = file_ptr.zig_module;
303 const rels = &zig_module.relocs.items[self.relocs_section_index];
301 assert(file_ptr == .zig_object);
302 const zig_object = file_ptr.zig_object;
303 const rels = &zig_object.relocs.items[self.relocs_section_index];
304304 try rels.append(gpa, reloc);
305305}
306306
307307pub fn freeRelocs(self: Atom, elf_file: *Elf) void {
308308 const file_ptr = self.file(elf_file).?;
309 assert(file_ptr == .zig_module);
310 const zig_module = file_ptr.zig_module;
311 zig_module.relocs.items[self.relocs_section_index].clearRetainingCapacity();
309 assert(file_ptr == .zig_object);
310 const zig_object = file_ptr.zig_object;
311 zig_object.relocs.items[self.relocs_section_index].clearRetainingCapacity();
312312}
313313
314314pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) bool {
......@@ -332,7 +332,7 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype
332332 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
333333
334334 const symbol_index = switch (file_ptr) {
335 .zig_module => |x| x.symbol(rel.r_sym()),
335 .zig_object => |x| x.symbol(rel.r_sym()),
336336 .object => |x| x.symbols.items[rel.r_sym()],
337337 else => unreachable,
338338 };
......@@ -690,7 +690,7 @@ fn reportUndefined(
690690 undefs: anytype,
691691) !void {
692692 const rel_esym = switch (self.file(elf_file).?) {
693 .zig_module => |x| x.elfSym(rel.r_sym()).*,
693 .zig_object => |x| x.elfSym(rel.r_sym()).*,
694694 .object => |x| x.symtab[rel.r_sym()],
695695 else => unreachable,
696696 };
......@@ -724,7 +724,7 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) !void {
724724 if (r_type == elf.R_X86_64_NONE) continue;
725725
726726 const target = switch (file_ptr) {
727 .zig_module => |x| elf_file.symbol(x.symbol(rel.r_sym())),
727 .zig_object => |x| elf_file.symbol(x.symbol(rel.r_sym())),
728728 .object => |x| elf_file.symbol(x.symbols.items[rel.r_sym()]),
729729 else => unreachable,
730730 };
......@@ -1004,7 +1004,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any
10041004 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
10051005
10061006 const target_index = switch (file_ptr) {
1007 .zig_module => |x| x.symbol(rel.r_sym()),
1007 .zig_object => |x| x.symbol(rel.r_sym()),
10081008 .object => |x| x.symbols.items[rel.r_sym()],
10091009 else => unreachable,
10101010 };
src/link/Elf/Symbol.zig+1-2
......@@ -72,7 +72,7 @@ pub fn file(symbol: Symbol, elf_file: *Elf) ?File {
7272pub fn elfSym(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym {
7373 const file_ptr = symbol.file(elf_file).?;
7474 switch (file_ptr) {
75 .zig_module => |x| return x.elfSym(symbol.esym_index).*,
75 .zig_object => |x| return x.elfSym(symbol.esym_index).*,
7676 .linker_defined => |x| return x.symtab.items[symbol.esym_index],
7777 inline else => |x| return x.symtab[symbol.esym_index],
7878 }
......@@ -406,4 +406,3 @@ const PltSection = synthetic_sections.PltSection;
406406const SharedObject = @import("SharedObject.zig");
407407const Symbol = @This();
408408const ZigGotSection = synthetic_sections.ZigGotSection;
409const ZigModule = @import("ZigModule.zig");
src/link/Elf/ZigModule.zig deleted-381
......@@ -1,381 +0,0 @@
1//! ZigModule encapsulates the state of the incrementally compiled Zig module.
2//! It stores the associated input local and global symbols, allocated atoms,
3//! and any relocations that may have been emitted.
4//! Think about this as fake in-memory Object file for the Zig module.
5
6/// Path is owned by Module and lives as long as *Module.
7path: []const u8,
8index: File.Index,
9
10local_esyms: std.MultiArrayList(ElfSym) = .{},
11global_esyms: std.MultiArrayList(ElfSym) = .{},
12local_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
13global_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
14globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},
15
16atoms: std.ArrayListUnmanaged(Atom.Index) = .{},
17relocs: std.ArrayListUnmanaged(std.ArrayListUnmanaged(elf.Elf64_Rela)) = .{},
18
19num_dynrelocs: u32 = 0,
20
21output_symtab_size: Elf.SymtabSize = .{},
22
23pub const global_symbol_bit: u32 = 0x80000000;
24pub const symbol_mask: u32 = 0x7fffffff;
25pub const SHN_ATOM: u16 = 0x100;
26
27pub fn deinit(self: *ZigModule, allocator: Allocator) void {
28 self.local_esyms.deinit(allocator);
29 self.global_esyms.deinit(allocator);
30 self.local_symbols.deinit(allocator);
31 self.global_symbols.deinit(allocator);
32 self.globals_lookup.deinit(allocator);
33 self.atoms.deinit(allocator);
34 for (self.relocs.items) |*list| {
35 list.deinit(allocator);
36 }
37 self.relocs.deinit(allocator);
38}
39
40pub fn addLocalEsym(self: *ZigModule, allocator: Allocator) !Symbol.Index {
41 try self.local_esyms.ensureUnusedCapacity(allocator, 1);
42 const index = @as(Symbol.Index, @intCast(self.local_esyms.addOneAssumeCapacity()));
43 var esym = ElfSym{ .elf_sym = Elf.null_sym };
44 esym.elf_sym.st_info = elf.STB_LOCAL << 4;
45 self.local_esyms.set(index, esym);
46 return index;
47}
48
49pub fn addGlobalEsym(self: *ZigModule, allocator: Allocator) !Symbol.Index {
50 try self.global_esyms.ensureUnusedCapacity(allocator, 1);
51 const index = @as(Symbol.Index, @intCast(self.global_esyms.addOneAssumeCapacity()));
52 var esym = ElfSym{ .elf_sym = Elf.null_sym };
53 esym.elf_sym.st_info = elf.STB_GLOBAL << 4;
54 self.global_esyms.set(index, esym);
55 return index | global_symbol_bit;
56}
57
58pub fn addAtom(self: *ZigModule, elf_file: *Elf) !Symbol.Index {
59 const gpa = elf_file.base.allocator;
60
61 const atom_index = try elf_file.addAtom();
62 const symbol_index = try elf_file.addSymbol();
63 const esym_index = try self.addLocalEsym(gpa);
64
65 const shndx = @as(u32, @intCast(self.atoms.items.len));
66 try self.atoms.append(gpa, atom_index);
67 try self.local_symbols.append(gpa, symbol_index);
68
69 const atom_ptr = elf_file.atom(atom_index).?;
70 atom_ptr.file_index = self.index;
71
72 const symbol_ptr = elf_file.symbol(symbol_index);
73 symbol_ptr.file_index = self.index;
74 symbol_ptr.atom_index = atom_index;
75
76 self.local_esyms.items(.shndx)[esym_index] = shndx;
77 self.local_esyms.items(.elf_sym)[esym_index].st_shndx = SHN_ATOM;
78 symbol_ptr.esym_index = esym_index;
79
80 const relocs_index = @as(u32, @intCast(self.relocs.items.len));
81 const relocs = try self.relocs.addOne(gpa);
82 relocs.* = .{};
83 atom_ptr.relocs_section_index = relocs_index;
84
85 return symbol_index;
86}
87
88/// TODO actually create fake input shdrs and return that instead.
89pub fn inputShdr(self: ZigModule, atom_index: Atom.Index, elf_file: *Elf) Object.ElfShdr {
90 _ = self;
91 const shdr = shdr: {
92 const atom = elf_file.atom(atom_index) orelse break :shdr Elf.null_shdr;
93 const shndx = atom.outputShndx() orelse break :shdr Elf.null_shdr;
94 var shdr = elf_file.shdrs.items[shndx];
95 shdr.sh_addr = 0;
96 shdr.sh_offset = 0;
97 shdr.sh_size = atom.size;
98 shdr.sh_addralign = atom.alignment.toByteUnits(1);
99 break :shdr shdr;
100 };
101 return Object.ElfShdr.fromElf64Shdr(shdr) catch unreachable;
102}
103
104pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void {
105 for (self.globals(), 0..) |index, i| {
106 const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit;
107 const esym = self.global_esyms.items(.elf_sym)[i];
108 const shndx = self.global_esyms.items(.shndx)[i];
109
110 if (esym.st_shndx == elf.SHN_UNDEF) continue;
111
112 if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) {
113 assert(esym.st_shndx == SHN_ATOM);
114 const atom_index = self.atoms.items[shndx];
115 const atom = elf_file.atom(atom_index) orelse continue;
116 if (!atom.flags.alive) continue;
117 }
118
119 const global = elf_file.symbol(index);
120 if (self.asFile().symbolRank(esym, false) < global.symbolRank(elf_file)) {
121 const atom_index = switch (esym.st_shndx) {
122 elf.SHN_ABS, elf.SHN_COMMON => 0,
123 SHN_ATOM => self.atoms.items[shndx],
124 else => unreachable,
125 };
126 const output_section_index = if (elf_file.atom(atom_index)) |atom|
127 atom.outputShndx().?
128 else
129 elf.SHN_UNDEF;
130 global.value = esym.st_value;
131 global.atom_index = atom_index;
132 global.esym_index = esym_index;
133 global.file_index = self.index;
134 global.output_section_index = output_section_index;
135 global.version_index = elf_file.default_sym_version;
136 if (esym.st_bind() == elf.STB_WEAK) global.flags.weak = true;
137 }
138 }
139}
140
141pub fn claimUnresolved(self: *ZigModule, elf_file: *Elf) void {
142 for (self.globals(), 0..) |index, i| {
143 const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit;
144 const esym = self.global_esyms.items(.elf_sym)[i];
145
146 if (esym.st_shndx != elf.SHN_UNDEF) continue;
147
148 const global = elf_file.symbol(index);
149 if (global.file(elf_file)) |_| {
150 if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF) continue;
151 }
152
153 const is_import = blk: {
154 if (!elf_file.isDynLib()) break :blk false;
155 const vis = @as(elf.STV, @enumFromInt(esym.st_other));
156 if (vis == .HIDDEN) break :blk false;
157 break :blk true;
158 };
159
160 global.value = 0;
161 global.atom_index = 0;
162 global.esym_index = esym_index;
163 global.file_index = self.index;
164 global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;
165 global.flags.import = is_import;
166 }
167}
168
169pub fn scanRelocs(self: *ZigModule, elf_file: *Elf, undefs: anytype) !void {
170 for (self.atoms.items) |atom_index| {
171 const atom = elf_file.atom(atom_index) orelse continue;
172 if (!atom.flags.alive) continue;
173 const shdr = atom.inputShdr(elf_file);
174 if (shdr.sh_type == elf.SHT_NOBITS) continue;
175 if (atom.scanRelocsRequiresCode(elf_file)) {
176 // TODO ideally we don't have to fetch the code here.
177 // Perhaps it would make sense to save the code until flushModule where we
178 // would free all of generated code?
179 const code = try self.codeAlloc(elf_file, atom_index);
180 defer elf_file.base.allocator.free(code);
181 try atom.scanRelocs(elf_file, code, undefs);
182 } else try atom.scanRelocs(elf_file, null, undefs);
183 }
184}
185
186pub fn resetGlobals(self: *ZigModule, elf_file: *Elf) void {
187 for (self.globals()) |index| {
188 const global = elf_file.symbol(index);
189 const off = global.name_offset;
190 global.* = .{};
191 global.name_offset = off;
192 }
193}
194
195pub fn markLive(self: *ZigModule, elf_file: *Elf) void {
196 for (self.globals(), 0..) |index, i| {
197 const esym = self.global_esyms.items(.elf_sym)[i];
198 if (esym.st_bind() == elf.STB_WEAK) continue;
199
200 const global = elf_file.symbol(index);
201 const file = global.file(elf_file) orelse continue;
202 const should_keep = esym.st_shndx == elf.SHN_UNDEF or
203 (esym.st_shndx == elf.SHN_COMMON and global.elfSym(elf_file).st_shndx != elf.SHN_COMMON);
204 if (should_keep and !file.isAlive()) {
205 file.setAlive();
206 file.markLive(elf_file);
207 }
208 }
209}
210
211pub fn updateSymtabSize(self: *ZigModule, elf_file: *Elf) void {
212 for (self.locals()) |local_index| {
213 const local = elf_file.symbol(local_index);
214 const esym = local.elfSym(elf_file);
215 switch (esym.st_type()) {
216 elf.STT_SECTION, elf.STT_NOTYPE => {
217 local.flags.output_symtab = false;
218 continue;
219 },
220 else => {},
221 }
222 local.flags.output_symtab = true;
223 self.output_symtab_size.nlocals += 1;
224 }
225
226 for (self.globals()) |global_index| {
227 const global = elf_file.symbol(global_index);
228 if (global.file(elf_file)) |file| if (file.index() != self.index) {
229 global.flags.output_symtab = false;
230 continue;
231 };
232 global.flags.output_symtab = true;
233 if (global.isLocal()) {
234 self.output_symtab_size.nlocals += 1;
235 } else {
236 self.output_symtab_size.nglobals += 1;
237 }
238 }
239}
240
241pub fn writeSymtab(self: *ZigModule, elf_file: *Elf, ctx: anytype) void {
242 var ilocal = ctx.ilocal;
243 for (self.locals()) |local_index| {
244 const local = elf_file.symbol(local_index);
245 if (!local.flags.output_symtab) continue;
246 local.setOutputSym(elf_file, &ctx.symtab[ilocal]);
247 ilocal += 1;
248 }
249
250 var iglobal = ctx.iglobal;
251 for (self.globals()) |global_index| {
252 const global = elf_file.symbol(global_index);
253 if (global.file(elf_file)) |file| if (file.index() != self.index) continue;
254 if (!global.flags.output_symtab) continue;
255 if (global.isLocal()) {
256 global.setOutputSym(elf_file, &ctx.symtab[ilocal]);
257 ilocal += 1;
258 } else {
259 global.setOutputSym(elf_file, &ctx.symtab[iglobal]);
260 iglobal += 1;
261 }
262 }
263}
264
265pub fn symbol(self: *ZigModule, index: Symbol.Index) Symbol.Index {
266 const is_global = index & global_symbol_bit != 0;
267 const actual_index = index & symbol_mask;
268 if (is_global) return self.global_symbols.items[actual_index];
269 return self.local_symbols.items[actual_index];
270}
271
272pub fn elfSym(self: *ZigModule, index: Symbol.Index) *elf.Elf64_Sym {
273 const is_global = index & global_symbol_bit != 0;
274 const actual_index = index & symbol_mask;
275 if (is_global) return &self.global_esyms.items(.elf_sym)[actual_index];
276 return &self.local_esyms.items(.elf_sym)[actual_index];
277}
278
279pub fn locals(self: *ZigModule) []const Symbol.Index {
280 return self.local_symbols.items;
281}
282
283pub fn globals(self: *ZigModule) []const Symbol.Index {
284 return self.global_symbols.items;
285}
286
287pub fn asFile(self: *ZigModule) File {
288 return .{ .zig_module = self };
289}
290
291/// Returns atom's code.
292/// Caller owns the memory.
293pub fn codeAlloc(self: ZigModule, elf_file: *Elf, atom_index: Atom.Index) ![]u8 {
294 const gpa = elf_file.base.allocator;
295 const atom = elf_file.atom(atom_index).?;
296 assert(atom.file_index == self.index);
297 const shdr = &elf_file.shdrs.items[atom.outputShndx().?];
298 const file_offset = shdr.sh_offset + atom.value - shdr.sh_addr;
299 const size = std.math.cast(usize, atom.size) orelse return error.Overflow;
300 const code = try gpa.alloc(u8, size);
301 errdefer gpa.free(code);
302 const amt = try elf_file.base.file.?.preadAll(code, file_offset);
303 if (amt != code.len) {
304 log.err("fetching code for {s} failed", .{atom.name(elf_file)});
305 return error.InputOutput;
306 }
307 return code;
308}
309
310pub fn fmtSymtab(self: *ZigModule, elf_file: *Elf) std.fmt.Formatter(formatSymtab) {
311 return .{ .data = .{
312 .self = self,
313 .elf_file = elf_file,
314 } };
315}
316
317const FormatContext = struct {
318 self: *ZigModule,
319 elf_file: *Elf,
320};
321
322fn formatSymtab(
323 ctx: FormatContext,
324 comptime unused_fmt_string: []const u8,
325 options: std.fmt.FormatOptions,
326 writer: anytype,
327) !void {
328 _ = unused_fmt_string;
329 _ = options;
330 try writer.writeAll(" locals\n");
331 for (ctx.self.locals()) |index| {
332 const local = ctx.elf_file.symbol(index);
333 try writer.print(" {}\n", .{local.fmt(ctx.elf_file)});
334 }
335 try writer.writeAll(" globals\n");
336 for (ctx.self.globals()) |index| {
337 const global = ctx.elf_file.symbol(index);
338 try writer.print(" {}\n", .{global.fmt(ctx.elf_file)});
339 }
340}
341
342pub fn fmtAtoms(self: *ZigModule, elf_file: *Elf) std.fmt.Formatter(formatAtoms) {
343 return .{ .data = .{
344 .self = self,
345 .elf_file = elf_file,
346 } };
347}
348
349fn formatAtoms(
350 ctx: FormatContext,
351 comptime unused_fmt_string: []const u8,
352 options: std.fmt.FormatOptions,
353 writer: anytype,
354) !void {
355 _ = unused_fmt_string;
356 _ = options;
357 try writer.writeAll(" atoms\n");
358 for (ctx.self.atoms.items) |atom_index| {
359 const atom = ctx.elf_file.atom(atom_index) orelse continue;
360 try writer.print(" {}\n", .{atom.fmt(ctx.elf_file)});
361 }
362}
363
364const ElfSym = struct {
365 elf_sym: elf.Elf64_Sym,
366 shndx: u32 = elf.SHN_UNDEF,
367};
368
369const assert = std.debug.assert;
370const std = @import("std");
371const elf = std.elf;
372const log = std.log.scoped(.link);
373
374const Allocator = std.mem.Allocator;
375const Atom = @import("Atom.zig");
376const Elf = @import("../Elf.zig");
377const File = @import("file.zig").File;
378const Module = @import("../../Module.zig");
379const Object = @import("Object.zig");
380const Symbol = @import("Symbol.zig");
381const ZigModule = @This();
src/link/Elf/ZigObject.zig created+381
......@@ -0,0 +1,381 @@
1//! ZigModule encapsulates the state of the incrementally compiled Zig module.
2//! It stores the associated input local and global symbols, allocated atoms,
3//! and any relocations that may have been emitted.
4//! Think about this as fake in-memory Object file for the Zig module.
5
6/// Path is owned by Module and lives as long as *Module.
7path: []const u8,
8index: File.Index,
9
10local_esyms: std.MultiArrayList(ElfSym) = .{},
11global_esyms: std.MultiArrayList(ElfSym) = .{},
12local_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
13global_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
14globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},
15
16atoms: std.ArrayListUnmanaged(Atom.Index) = .{},
17relocs: std.ArrayListUnmanaged(std.ArrayListUnmanaged(elf.Elf64_Rela)) = .{},
18
19num_dynrelocs: u32 = 0,
20
21output_symtab_size: Elf.SymtabSize = .{},
22
23pub const global_symbol_bit: u32 = 0x80000000;
24pub const symbol_mask: u32 = 0x7fffffff;
25pub const SHN_ATOM: u16 = 0x100;
26
27pub fn deinit(self: *ZigModule, allocator: Allocator) void {
28 self.local_esyms.deinit(allocator);
29 self.global_esyms.deinit(allocator);
30 self.local_symbols.deinit(allocator);
31 self.global_symbols.deinit(allocator);
32 self.globals_lookup.deinit(allocator);
33 self.atoms.deinit(allocator);
34 for (self.relocs.items) |*list| {
35 list.deinit(allocator);
36 }
37 self.relocs.deinit(allocator);
38}
39
40pub fn addLocalEsym(self: *ZigModule, allocator: Allocator) !Symbol.Index {
41 try self.local_esyms.ensureUnusedCapacity(allocator, 1);
42 const index = @as(Symbol.Index, @intCast(self.local_esyms.addOneAssumeCapacity()));
43 var esym = ElfSym{ .elf_sym = Elf.null_sym };
44 esym.elf_sym.st_info = elf.STB_LOCAL << 4;
45 self.local_esyms.set(index, esym);
46 return index;
47}
48
49pub fn addGlobalEsym(self: *ZigModule, allocator: Allocator) !Symbol.Index {
50 try self.global_esyms.ensureUnusedCapacity(allocator, 1);
51 const index = @as(Symbol.Index, @intCast(self.global_esyms.addOneAssumeCapacity()));
52 var esym = ElfSym{ .elf_sym = Elf.null_sym };
53 esym.elf_sym.st_info = elf.STB_GLOBAL << 4;
54 self.global_esyms.set(index, esym);
55 return index | global_symbol_bit;
56}
57
58pub fn addAtom(self: *ZigModule, elf_file: *Elf) !Symbol.Index {
59 const gpa = elf_file.base.allocator;
60
61 const atom_index = try elf_file.addAtom();
62 const symbol_index = try elf_file.addSymbol();
63 const esym_index = try self.addLocalEsym(gpa);
64
65 const shndx = @as(u32, @intCast(self.atoms.items.len));
66 try self.atoms.append(gpa, atom_index);
67 try self.local_symbols.append(gpa, symbol_index);
68
69 const atom_ptr = elf_file.atom(atom_index).?;
70 atom_ptr.file_index = self.index;
71
72 const symbol_ptr = elf_file.symbol(symbol_index);
73 symbol_ptr.file_index = self.index;
74 symbol_ptr.atom_index = atom_index;
75
76 self.local_esyms.items(.shndx)[esym_index] = shndx;
77 self.local_esyms.items(.elf_sym)[esym_index].st_shndx = SHN_ATOM;
78 symbol_ptr.esym_index = esym_index;
79
80 const relocs_index = @as(u32, @intCast(self.relocs.items.len));
81 const relocs = try self.relocs.addOne(gpa);
82 relocs.* = .{};
83 atom_ptr.relocs_section_index = relocs_index;
84
85 return symbol_index;
86}
87
88/// TODO actually create fake input shdrs and return that instead.
89pub fn inputShdr(self: ZigModule, atom_index: Atom.Index, elf_file: *Elf) Object.ElfShdr {
90 _ = self;
91 const shdr = shdr: {
92 const atom = elf_file.atom(atom_index) orelse break :shdr Elf.null_shdr;
93 const shndx = atom.outputShndx() orelse break :shdr Elf.null_shdr;
94 var shdr = elf_file.shdrs.items[shndx];
95 shdr.sh_addr = 0;
96 shdr.sh_offset = 0;
97 shdr.sh_size = atom.size;
98 shdr.sh_addralign = atom.alignment.toByteUnits(1);
99 break :shdr shdr;
100 };
101 return Object.ElfShdr.fromElf64Shdr(shdr) catch unreachable;
102}
103
104pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void {
105 for (self.globals(), 0..) |index, i| {
106 const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit;
107 const esym = self.global_esyms.items(.elf_sym)[i];
108 const shndx = self.global_esyms.items(.shndx)[i];
109
110 if (esym.st_shndx == elf.SHN_UNDEF) continue;
111
112 if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) {
113 assert(esym.st_shndx == SHN_ATOM);
114 const atom_index = self.atoms.items[shndx];
115 const atom = elf_file.atom(atom_index) orelse continue;
116 if (!atom.flags.alive) continue;
117 }
118
119 const global = elf_file.symbol(index);
120 if (self.asFile().symbolRank(esym, false) < global.symbolRank(elf_file)) {
121 const atom_index = switch (esym.st_shndx) {
122 elf.SHN_ABS, elf.SHN_COMMON => 0,
123 SHN_ATOM => self.atoms.items[shndx],
124 else => unreachable,
125 };
126 const output_section_index = if (elf_file.atom(atom_index)) |atom|
127 atom.outputShndx().?
128 else
129 elf.SHN_UNDEF;
130 global.value = esym.st_value;
131 global.atom_index = atom_index;
132 global.esym_index = esym_index;
133 global.file_index = self.index;
134 global.output_section_index = output_section_index;
135 global.version_index = elf_file.default_sym_version;
136 if (esym.st_bind() == elf.STB_WEAK) global.flags.weak = true;
137 }
138 }
139}
140
141pub fn claimUnresolved(self: *ZigModule, elf_file: *Elf) void {
142 for (self.globals(), 0..) |index, i| {
143 const esym_index = @as(Symbol.Index, @intCast(i)) | global_symbol_bit;
144 const esym = self.global_esyms.items(.elf_sym)[i];
145
146 if (esym.st_shndx != elf.SHN_UNDEF) continue;
147
148 const global = elf_file.symbol(index);
149 if (global.file(elf_file)) |_| {
150 if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF) continue;
151 }
152
153 const is_import = blk: {
154 if (!elf_file.isDynLib()) break :blk false;
155 const vis = @as(elf.STV, @enumFromInt(esym.st_other));
156 if (vis == .HIDDEN) break :blk false;
157 break :blk true;
158 };
159
160 global.value = 0;
161 global.atom_index = 0;
162 global.esym_index = esym_index;
163 global.file_index = self.index;
164 global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;
165 global.flags.import = is_import;
166 }
167}
168
169pub fn scanRelocs(self: *ZigModule, elf_file: *Elf, undefs: anytype) !void {
170 for (self.atoms.items) |atom_index| {
171 const atom = elf_file.atom(atom_index) orelse continue;
172 if (!atom.flags.alive) continue;
173 const shdr = atom.inputShdr(elf_file);
174 if (shdr.sh_type == elf.SHT_NOBITS) continue;
175 if (atom.scanRelocsRequiresCode(elf_file)) {
176 // TODO ideally we don't have to fetch the code here.
177 // Perhaps it would make sense to save the code until flushModule where we
178 // would free all of generated code?
179 const code = try self.codeAlloc(elf_file, atom_index);
180 defer elf_file.base.allocator.free(code);
181 try atom.scanRelocs(elf_file, code, undefs);
182 } else try atom.scanRelocs(elf_file, null, undefs);
183 }
184}
185
186pub fn resetGlobals(self: *ZigModule, elf_file: *Elf) void {
187 for (self.globals()) |index| {
188 const global = elf_file.symbol(index);
189 const off = global.name_offset;
190 global.* = .{};
191 global.name_offset = off;
192 }
193}
194
195pub fn markLive(self: *ZigModule, elf_file: *Elf) void {
196 for (self.globals(), 0..) |index, i| {
197 const esym = self.global_esyms.items(.elf_sym)[i];
198 if (esym.st_bind() == elf.STB_WEAK) continue;
199
200 const global = elf_file.symbol(index);
201 const file = global.file(elf_file) orelse continue;
202 const should_keep = esym.st_shndx == elf.SHN_UNDEF or
203 (esym.st_shndx == elf.SHN_COMMON and global.elfSym(elf_file).st_shndx != elf.SHN_COMMON);
204 if (should_keep and !file.isAlive()) {
205 file.setAlive();
206 file.markLive(elf_file);
207 }
208 }
209}
210
211pub fn updateSymtabSize(self: *ZigModule, elf_file: *Elf) void {
212 for (self.locals()) |local_index| {
213 const local = elf_file.symbol(local_index);
214 const esym = local.elfSym(elf_file);
215 switch (esym.st_type()) {
216 elf.STT_SECTION, elf.STT_NOTYPE => {
217 local.flags.output_symtab = false;
218 continue;
219 },
220 else => {},
221 }
222 local.flags.output_symtab = true;
223 self.output_symtab_size.nlocals += 1;
224 }
225
226 for (self.globals()) |global_index| {
227 const global = elf_file.symbol(global_index);
228 if (global.file(elf_file)) |file| if (file.index() != self.index) {
229 global.flags.output_symtab = false;
230 continue;
231 };
232 global.flags.output_symtab = true;
233 if (global.isLocal()) {
234 self.output_symtab_size.nlocals += 1;
235 } else {
236 self.output_symtab_size.nglobals += 1;
237 }
238 }
239}
240
241pub fn writeSymtab(self: *ZigModule, elf_file: *Elf, ctx: anytype) void {
242 var ilocal = ctx.ilocal;
243 for (self.locals()) |local_index| {
244 const local = elf_file.symbol(local_index);
245 if (!local.flags.output_symtab) continue;
246 local.setOutputSym(elf_file, &ctx.symtab[ilocal]);
247 ilocal += 1;
248 }
249
250 var iglobal = ctx.iglobal;
251 for (self.globals()) |global_index| {
252 const global = elf_file.symbol(global_index);
253 if (global.file(elf_file)) |file| if (file.index() != self.index) continue;
254 if (!global.flags.output_symtab) continue;
255 if (global.isLocal()) {
256 global.setOutputSym(elf_file, &ctx.symtab[ilocal]);
257 ilocal += 1;
258 } else {
259 global.setOutputSym(elf_file, &ctx.symtab[iglobal]);
260 iglobal += 1;
261 }
262 }
263}
264
265pub fn symbol(self: *ZigModule, index: Symbol.Index) Symbol.Index {
266 const is_global = index & global_symbol_bit != 0;
267 const actual_index = index & symbol_mask;
268 if (is_global) return self.global_symbols.items[actual_index];
269 return self.local_symbols.items[actual_index];
270}
271
272pub fn elfSym(self: *ZigModule, index: Symbol.Index) *elf.Elf64_Sym {
273 const is_global = index & global_symbol_bit != 0;
274 const actual_index = index & symbol_mask;
275 if (is_global) return &self.global_esyms.items(.elf_sym)[actual_index];
276 return &self.local_esyms.items(.elf_sym)[actual_index];
277}
278
279pub fn locals(self: *ZigModule) []const Symbol.Index {
280 return self.local_symbols.items;
281}
282
283pub fn globals(self: *ZigModule) []const Symbol.Index {
284 return self.global_symbols.items;
285}
286
287pub fn asFile(self: *ZigModule) File {
288 return .{ .zig_object = self };
289}
290
291/// Returns atom's code.
292/// Caller owns the memory.
293pub fn codeAlloc(self: ZigModule, elf_file: *Elf, atom_index: Atom.Index) ![]u8 {
294 const gpa = elf_file.base.allocator;
295 const atom = elf_file.atom(atom_index).?;
296 assert(atom.file_index == self.index);
297 const shdr = &elf_file.shdrs.items[atom.outputShndx().?];
298 const file_offset = shdr.sh_offset + atom.value - shdr.sh_addr;
299 const size = std.math.cast(usize, atom.size) orelse return error.Overflow;
300 const code = try gpa.alloc(u8, size);
301 errdefer gpa.free(code);
302 const amt = try elf_file.base.file.?.preadAll(code, file_offset);
303 if (amt != code.len) {
304 log.err("fetching code for {s} failed", .{atom.name(elf_file)});
305 return error.InputOutput;
306 }
307 return code;
308}
309
310pub fn fmtSymtab(self: *ZigModule, elf_file: *Elf) std.fmt.Formatter(formatSymtab) {
311 return .{ .data = .{
312 .self = self,
313 .elf_file = elf_file,
314 } };
315}
316
317const FormatContext = struct {
318 self: *ZigModule,
319 elf_file: *Elf,
320};
321
322fn formatSymtab(
323 ctx: FormatContext,
324 comptime unused_fmt_string: []const u8,
325 options: std.fmt.FormatOptions,
326 writer: anytype,
327) !void {
328 _ = unused_fmt_string;
329 _ = options;
330 try writer.writeAll(" locals\n");
331 for (ctx.self.locals()) |index| {
332 const local = ctx.elf_file.symbol(index);
333 try writer.print(" {}\n", .{local.fmt(ctx.elf_file)});
334 }
335 try writer.writeAll(" globals\n");
336 for (ctx.self.globals()) |index| {
337 const global = ctx.elf_file.symbol(index);
338 try writer.print(" {}\n", .{global.fmt(ctx.elf_file)});
339 }
340}
341
342pub fn fmtAtoms(self: *ZigModule, elf_file: *Elf) std.fmt.Formatter(formatAtoms) {
343 return .{ .data = .{
344 .self = self,
345 .elf_file = elf_file,
346 } };
347}
348
349fn formatAtoms(
350 ctx: FormatContext,
351 comptime unused_fmt_string: []const u8,
352 options: std.fmt.FormatOptions,
353 writer: anytype,
354) !void {
355 _ = unused_fmt_string;
356 _ = options;
357 try writer.writeAll(" atoms\n");
358 for (ctx.self.atoms.items) |atom_index| {
359 const atom = ctx.elf_file.atom(atom_index) orelse continue;
360 try writer.print(" {}\n", .{atom.fmt(ctx.elf_file)});
361 }
362}
363
364const ElfSym = struct {
365 elf_sym: elf.Elf64_Sym,
366 shndx: u32 = elf.SHN_UNDEF,
367};
368
369const assert = std.debug.assert;
370const std = @import("std");
371const elf = std.elf;
372const log = std.log.scoped(.link);
373
374const Allocator = std.mem.Allocator;
375const Atom = @import("Atom.zig");
376const Elf = @import("../Elf.zig");
377const File = @import("file.zig").File;
378const Module = @import("../../Module.zig");
379const Object = @import("Object.zig");
380const Symbol = @import("Symbol.zig");
381const ZigModule = @This();
src/link/Elf/file.zig+7-7
......@@ -1,5 +1,5 @@
11pub const File = union(enum) {
2 zig_module: *ZigModule,
2 zig_object: *ZigObject,
33 linker_defined: *LinkerDefined,
44 object: *Object,
55 shared_object: *SharedObject,
......@@ -23,7 +23,7 @@ pub const File = union(enum) {
2323 _ = unused_fmt_string;
2424 _ = options;
2525 switch (file) {
26 .zig_module => |x| try writer.print("{s}", .{x.path}),
26 .zig_object => |x| try writer.print("{s}", .{x.path}),
2727 .linker_defined => try writer.writeAll("(linker defined)"),
2828 .object => |x| try writer.print("{}", .{x.fmtPath()}),
2929 .shared_object => |x| try writer.writeAll(x.path),
......@@ -32,7 +32,7 @@ pub const File = union(enum) {
3232
3333 pub fn isAlive(file: File) bool {
3434 return switch (file) {
35 .zig_module => true,
35 .zig_object => true,
3636 .linker_defined => true,
3737 inline else => |x| x.alive,
3838 };
......@@ -76,7 +76,7 @@ pub const File = union(enum) {
7676
7777 pub fn setAlive(file: File) void {
7878 switch (file) {
79 .zig_module, .linker_defined => {},
79 .zig_object, .linker_defined => {},
8080 inline else => |x| x.alive = true,
8181 }
8282 }
......@@ -92,7 +92,7 @@ pub const File = union(enum) {
9292 return switch (file) {
9393 .linker_defined => unreachable,
9494 .shared_object => unreachable,
95 .zig_module => |x| x.atoms.items,
95 .zig_object => |x| x.atoms.items,
9696 .object => |x| x.atoms.items,
9797 };
9898 }
......@@ -115,7 +115,7 @@ pub const File = union(enum) {
115115
116116 pub const Entry = union(enum) {
117117 null: void,
118 zig_module: ZigModule,
118 zig_object: ZigObject,
119119 linker_defined: LinkerDefined,
120120 object: Object,
121121 shared_object: SharedObject,
......@@ -132,4 +132,4 @@ const LinkerDefined = @import("LinkerDefined.zig");
132132const Object = @import("Object.zig");
133133const SharedObject = @import("SharedObject.zig");
134134const Symbol = @import("Symbol.zig");
135const ZigModule = @import("ZigModule.zig");
135const ZigObject = @import("ZigObject.zig");