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...@@ -594,7 +594,7 @@ set(ZIG_STAGE2_SOURCES
594 "${CMAKE_SOURCE_DIR}/src/link/Elf/Object.zig"594 "${CMAKE_SOURCE_DIR}/src/link/Elf/Object.zig"
595 "${CMAKE_SOURCE_DIR}/src/link/Elf/SharedObject.zig"595 "${CMAKE_SOURCE_DIR}/src/link/Elf/SharedObject.zig"
596 "${CMAKE_SOURCE_DIR}/src/link/Elf/Symbol.zig"596 "${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"
598 "${CMAKE_SOURCE_DIR}/src/link/Elf/eh_frame.zig"598 "${CMAKE_SOURCE_DIR}/src/link/Elf/eh_frame.zig"
599 "${CMAKE_SOURCE_DIR}/src/link/Elf/file.zig"599 "${CMAKE_SOURCE_DIR}/src/link/Elf/file.zig"
600 "${CMAKE_SOURCE_DIR}/src/link/Elf/gc.zig"600 "${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 {...@@ -86,7 +86,7 @@ pub fn emitMir(emit: *Emit) Error!void {
86 }),86 }),
87 .linker_reloc => |data| if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| {87 .linker_reloc => |data| if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| {
88 const atom = elf_file.symbol(data.atom_index).atom(elf_file).?;88 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));
90 if (emit.lower.bin_file.options.pic) {90 if (emit.lower.bin_file.options.pic) {
91 const r_type: u32 = if (sym.flags.has_zig_got)91 const r_type: u32 = if (sym.flags.has_zig_got)
92 link.File.Elf.R_X86_64_ZIG_GOTPCREL92 link.File.Elf.R_X86_64_ZIG_GOTPCREL
src/codegen.zig+1-1
...@@ -904,7 +904,7 @@ fn genDeclRef(...@@ -904,7 +904,7 @@ fn genDeclRef(
904 else904 else
905 null;905 null;
906 const sym_index = try elf_file.getGlobalSymbol(name, lib_name);906 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;
908 return GenResult.mcv(.{ .load_symbol = sym_index });908 return GenResult.mcv(.{ .load_symbol = sym_index });
909 }909 }
910 const sym_index = try elf_file.getOrCreateMetadataForDecl(decl_index);910 const sym_index = try elf_file.getOrCreateMetadataForDecl(decl_index);
src/link/Elf.zig+87-95
...@@ -11,7 +11,7 @@ llvm_object: ?*LlvmObject = null,...@@ -11,7 +11,7 @@ llvm_object: ?*LlvmObject = null,
11/// Index of each input file also encodes the priority or precedence of one input file11/// Index of each input file also encodes the priority or precedence of one input file
12/// over another.12/// over another.
13files: std.MultiArrayList(File.Entry) = .{},13files: std.MultiArrayList(File.Entry) = .{},
14zig_module_index: ?File.Index = null,14zig_object_index: ?File.Index = null,
15linker_defined_index: ?File.Index = null,15linker_defined_index: ?File.Index = null,
16objects: std.ArrayListUnmanaged(File.Index) = .{},16objects: std.ArrayListUnmanaged(File.Index) = .{},
17shared_objects: std.ArrayListUnmanaged(File.Index) = .{},17shared_objects: std.ArrayListUnmanaged(File.Index) = .{},
...@@ -327,24 +327,24 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option...@@ -327,24 +327,24 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
327 }327 }
328328
329 const index = @as(File.Index, @intCast(try self.files.addOne(allocator)));329 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 = .{
331 .index = index,331 .index = index,
332 .path = options.module.?.main_mod.root_src_path,332 .path = options.module.?.main_mod.root_src_path,
333 } });333 } });
334 self.zig_module_index = index;334 self.zig_object_index = index;
335 const zig_module = self.file(index).?.zig_module;335 const zig_object = self.zigObjectPtr().?;
336336
337 try zig_module.atoms.append(allocator, 0); // null input section337 try zig_object.atoms.append(allocator, 0); // null input section
338338
339 const name_off = try self.strtab.insert(allocator, std.fs.path.stem(options.module.?.main_mod.root_src_path));339 const name_off = try self.strtab.insert(allocator, std.fs.path.stem(options.module.?.main_mod.root_src_path));
340 const symbol_index = try self.addSymbol();340 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);
342 const symbol_ptr = self.symbol(symbol_index);342 const symbol_ptr = self.symbol(symbol_index);
343 symbol_ptr.file_index = zig_module.index;343 symbol_ptr.file_index = zig_object.index;
344 symbol_ptr.name_offset = name_off;344 symbol_ptr.name_offset = name_off;
345345
346 const esym_index = try zig_module.addLocalEsym(allocator);346 const esym_index = try zig_object.addLocalEsym(allocator);
347 const esym = &zig_module.local_esyms.items(.elf_sym)[esym_index];347 const esym = &zig_object.local_esyms.items(.elf_sym)[esym_index];
348 esym.st_name = name_off;348 esym.st_name = name_off;
349 esym.st_info |= elf.STT_FILE;349 esym.st_info |= elf.STT_FILE;
350 esym.st_shndx = elf.SHN_ABS;350 esym.st_shndx = elf.SHN_ABS;
...@@ -401,7 +401,7 @@ pub fn deinit(self: *Elf) void {...@@ -401,7 +401,7 @@ pub fn deinit(self: *Elf) void {
401401
402 for (self.files.items(.tags), self.files.items(.data)) |tag, *data| switch (tag) {402 for (self.files.items(.tags), self.files.items(.data)) |tag, *data| switch (tag) {
403 .null => {},403 .null => {},
404 .zig_module => data.zig_module.deinit(gpa),404 .zig_object => data.zig_object.deinit(gpa),
405 .linker_defined => data.linker_defined.deinit(gpa),405 .linker_defined => data.linker_defined.deinit(gpa),
406 .object => data.object.deinit(gpa),406 .object => data.object.deinit(gpa),
407 .shared_object => data.shared_object.deinit(gpa),407 .shared_object => data.shared_object.deinit(gpa),
...@@ -726,7 +726,7 @@ fn allocateNonAllocSection(self: *Elf, opts: AllocateNonAllocSectionOpts) error{...@@ -726,7 +726,7 @@ fn allocateNonAllocSection(self: *Elf, opts: AllocateNonAllocSectionOpts) error{
726 return index;726 return index;
727}727}
728728
729/// TODO move to ZigModule729/// TODO move to ZigObject
730pub fn initMetadata(self: *Elf) !void {730pub fn initMetadata(self: *Elf) !void {
731 const gpa = self.base.allocator;731 const gpa = self.base.allocator;
732 const ptr_size = self.ptrWidthBytes();732 const ptr_size = self.ptrWidthBytes();
...@@ -1041,7 +1041,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1041,7 +1041,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1041 } else null;1041 } else null;
1042 const gc_sections = self.base.options.gc_sections orelse false;1042 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) {
1045 // TODO this will become -r route I guess. For now, just copy the object file.1045 // TODO this will become -r route I guess. For now, just copy the object file.
1046 assert(self.base.file == null); // TODO uncomment once we implement -r1046 assert(self.base.file == null); // TODO uncomment once we implement -r
1047 const the_object_path = blk: {1047 const the_object_path = blk: {
...@@ -1543,7 +1543,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1543,7 +1543,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1543 }1543 }
15441544
1545 // Now, we are ready to resolve the symbols across all input files.1545 // 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 parsed1546 // We will first resolve the files in the ZigObject, next in the parsed
1547 // input Object files.1547 // input Object files.
1548 // Any qualifing unresolved symbol will be upgraded to an absolute, weak1548 // Any qualifing unresolved symbol will be upgraded to an absolute, weak
1549 // symbol for potential resolution at load-time.1549 // symbol for potential resolution at load-time.
...@@ -1576,7 +1576,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1576,7 +1576,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1576 // Scan and create missing synthetic entries such as GOT indirection.1576 // Scan and create missing synthetic entries such as GOT indirection.
1577 try self.scanRelocs();1577 try self.scanRelocs();
15781578
1579 // TODO I need to re-think how to handle ZigModule's debug sections AND debug sections1579 // TODO I need to re-think how to handle ZigObject's debug sections AND debug sections
1580 // extracted from input object files correctly.1580 // extracted from input object files correctly.
1581 if (self.dwarf) |*dw| {1581 if (self.dwarf) |*dw| {
1582 if (self.debug_abbrev_section_dirty) {1582 if (self.debug_abbrev_section_dirty) {
...@@ -1645,15 +1645,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1645,15 +1645,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
16451645
1646 // Beyond this point, everything has been allocated a virtual address and we can resolve1646 // Beyond this point, everything has been allocated a virtual address and we can resolve
1647 // the relocations, and commit objects to file.1647 // the relocations, and commit objects to file.
1648 if (self.zig_module_index) |index| {1648 if (self.zigObjectPtr()) |zig_object| {
1649 const zig_module = self.file(index).?.zig_module;1649 for (zig_object.atoms.items) |atom_index| {
1650 for (zig_module.atoms.items) |atom_index| {
1651 const atom_ptr = self.atom(atom_index) orelse continue;1650 const atom_ptr = self.atom(atom_index) orelse continue;
1652 if (!atom_ptr.flags.alive) continue;1651 if (!atom_ptr.flags.alive) continue;
1653 const out_shndx = atom_ptr.outputShndx() orelse continue;1652 const out_shndx = atom_ptr.outputShndx() orelse continue;
1654 const shdr = &self.shdrs.items[out_shndx];1653 const shdr = &self.shdrs.items[out_shndx];
1655 if (shdr.sh_type == elf.SHT_NOBITS) continue;1654 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);
1657 defer gpa.free(code);1656 defer gpa.free(code);
1658 const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr;1657 const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr;
1659 atom_ptr.resolveRelocsAlloc(self, code) catch |err| switch (err) {1658 atom_ptr.resolveRelocsAlloc(self, code) catch |err| switch (err) {
...@@ -1926,8 +1925,8 @@ fn accessLibPath(...@@ -1926,8 +1925,8 @@ fn accessLibPath(
1926/// 5. Remove references to dead objects/shared objects1925/// 5. Remove references to dead objects/shared objects
1927/// 6. Re-run symbol resolution on pruned objects and shared objects sets.1926/// 6. Re-run symbol resolution on pruned objects and shared objects sets.
1928fn resolveSymbols(self: *Elf) void {1927fn resolveSymbols(self: *Elf) void {
1929 // Resolve symbols in the ZigModule. For now, we assume that it's always live.1928 // Resolve symbols in the ZigObject. For now, we assume that it's always live.
1930 if (self.zig_module_index) |index| self.file(index).?.resolveSymbols(self);1929 if (self.zigObjectPtr()) |zig_object| zig_object.resolveSymbols(self);
1931 // Resolve symbols on the set of all objects and shared objects (even if some are unneeded).1930 // Resolve symbols on the set of all objects and shared objects (even if some are unneeded).
1932 for (self.objects.items) |index| self.file(index).?.resolveSymbols(self);1931 for (self.objects.items) |index| self.file(index).?.resolveSymbols(self);
1933 for (self.shared_objects.items) |index| self.file(index).?.resolveSymbols(self);1932 for (self.shared_objects.items) |index| self.file(index).?.resolveSymbols(self);
...@@ -1936,7 +1935,7 @@ fn resolveSymbols(self: *Elf) void {...@@ -1936,7 +1935,7 @@ fn resolveSymbols(self: *Elf) void {
1936 self.markLive();1935 self.markLive();
19371936
1938 // Reset state of all globals after marking live objects.1937 // 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);
1940 for (self.objects.items) |index| self.file(index).?.resetGlobals(self);1939 for (self.objects.items) |index| self.file(index).?.resetGlobals(self);
1941 for (self.shared_objects.items) |index| self.file(index).?.resetGlobals(self);1940 for (self.shared_objects.items) |index| self.file(index).?.resetGlobals(self);
19421941
...@@ -1988,7 +1987,7 @@ fn resolveSymbols(self: *Elf) void {...@@ -1988,7 +1987,7 @@ fn resolveSymbols(self: *Elf) void {
1988 }1987 }
19891988
1990 // Re-resolve the symbols.1989 // 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);
1992 for (self.objects.items) |index| self.file(index).?.resolveSymbols(self);1991 for (self.objects.items) |index| self.file(index).?.resolveSymbols(self);
1993 for (self.shared_objects.items) |index| self.file(index).?.resolveSymbols(self);1992 for (self.shared_objects.items) |index| self.file(index).?.resolveSymbols(self);
1994}1993}
...@@ -1998,7 +1997,7 @@ fn resolveSymbols(self: *Elf) void {...@@ -1998,7 +1997,7 @@ fn resolveSymbols(self: *Elf) void {
1998/// This routine will prune unneeded objects extracted from archives and1997/// This routine will prune unneeded objects extracted from archives and
1999/// unneeded shared objects.1998/// unneeded shared objects.
2000fn markLive(self: *Elf) void {1999fn 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);
2002 for (self.objects.items) |index| {2001 for (self.objects.items) |index| {
2003 const file_ptr = self.file(index).?;2002 const file_ptr = self.file(index).?;
2004 if (file_ptr.isAlive()) file_ptr.markLive(self);2003 if (file_ptr.isAlive()) file_ptr.markLive(self);
...@@ -2057,7 +2056,7 @@ fn markImportsExports(self: *Elf) void {...@@ -2057,7 +2056,7 @@ fn markImportsExports(self: *Elf) void {
2057 }2056 }
2058 }2057 }
20592058
2060 if (self.zig_module_index) |index| {2059 if (self.zig_object_index) |index| {
2061 mark(self, index);2060 mark(self, index);
2062 }2061 }
20632062
...@@ -2067,9 +2066,8 @@ fn markImportsExports(self: *Elf) void {...@@ -2067,9 +2066,8 @@ fn markImportsExports(self: *Elf) void {
2067}2066}
20682067
2069fn claimUnresolved(self: *Elf) void {2068fn claimUnresolved(self: *Elf) void {
2070 if (self.zig_module_index) |index| {2069 if (self.zigObjectPtr()) |zig_object| {
2071 const zig_module = self.file(index).?.zig_module;2070 zig_object.claimUnresolved(self);
2072 zig_module.claimUnresolved(self);
2073 }2071 }
2074 for (self.objects.items) |index| {2072 for (self.objects.items) |index| {
2075 const object = self.file(index).?.object;2073 const object = self.file(index).?.object;
...@@ -2093,9 +2091,8 @@ fn scanRelocs(self: *Elf) !void {...@@ -2093,9 +2091,8 @@ fn scanRelocs(self: *Elf) !void {
2093 undefs.deinit();2091 undefs.deinit();
2094 }2092 }
20952093
2096 if (self.zig_module_index) |index| {2094 if (self.zigObjectPtr()) |zig_object| {
2097 const zig_module = self.file(index).?.zig_module;2095 try zig_object.scanRelocs(self, &undefs);
2098 try zig_module.scanRelocs(self, &undefs);
2099 }2096 }
2100 for (self.objects.items) |index| {2097 for (self.objects.items) |index| {
2101 const object = self.file(index).?.object;2098 const object = self.file(index).?.object;
...@@ -3114,9 +3111,9 @@ pub fn getOrCreateMetadataForLazySymbol(self: *Elf, lazy_sym: link.File.LazySymb...@@ -3114,9 +3111,9 @@ pub fn getOrCreateMetadataForLazySymbol(self: *Elf, lazy_sym: link.File.LazySymb
3114 .state = &gop.value_ptr.rodata_state,3111 .state = &gop.value_ptr.rodata_state,
3115 },3112 },
3116 };3113 };
3117 const zig_module = self.file(self.zig_module_index.?).?.zig_module;3114 const zig_object = self.zigObjectPtr().?;
3118 switch (metadata.state.*) {3115 switch (metadata.state.*) {
3119 .unused => metadata.symbol_index.* = try zig_module.addAtom(self),3116 .unused => metadata.symbol_index.* = try zig_object.addAtom(self),
3120 .pending_flush => return metadata.symbol_index.*,3117 .pending_flush => return metadata.symbol_index.*,
3121 .flushed => {},3118 .flushed => {},
3122 }3119 }
...@@ -3130,8 +3127,8 @@ pub fn getOrCreateMetadataForLazySymbol(self: *Elf, lazy_sym: link.File.LazySymb...@@ -3130,8 +3127,8 @@ pub fn getOrCreateMetadataForLazySymbol(self: *Elf, lazy_sym: link.File.LazySymb
3130pub fn getOrCreateMetadataForDecl(self: *Elf, decl_index: Module.Decl.Index) !Symbol.Index {3127pub fn getOrCreateMetadataForDecl(self: *Elf, decl_index: Module.Decl.Index) !Symbol.Index {
3131 const gop = try self.decls.getOrPut(self.base.allocator, decl_index);3128 const gop = try self.decls.getOrPut(self.base.allocator, decl_index);
3132 if (!gop.found_existing) {3129 if (!gop.found_existing) {
3133 const zig_module = self.file(self.zig_module_index.?).?.zig_module;3130 const zig_object = self.zigObjectPtr().?;
3134 gop.value_ptr.* = .{ .symbol_index = try zig_module.addAtom(self) };3131 gop.value_ptr.* = .{ .symbol_index = try zig_object.addAtom(self) };
3135 }3132 }
3136 return gop.value_ptr.symbol_index;3133 return gop.value_ptr.symbol_index;
3137}3134}
...@@ -3173,7 +3170,7 @@ fn updateDeclCode(...@@ -3173,7 +3170,7 @@ fn updateDeclCode(
3173) !void {3170) !void {
3174 const gpa = self.base.allocator;3171 const gpa = self.base.allocator;
3175 const mod = self.base.options.module.?;3172 const mod = self.base.options.module.?;
3176 const zig_module = self.file(self.zig_module_index.?).?.zig_module;3173 const zig_object = self.zigObjectPtr().?;
3177 const decl = mod.declPtr(decl_index);3174 const decl = mod.declPtr(decl_index);
31783175
3179 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));3176 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
...@@ -3182,7 +3179,7 @@ fn updateDeclCode(...@@ -3182,7 +3179,7 @@ fn updateDeclCode(
3182 const required_alignment = decl.getAlignment(mod);3179 const required_alignment = decl.getAlignment(mod);
31833180
3184 const sym = self.symbol(sym_index);3181 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];
3186 const atom_ptr = sym.atom(self).?;3183 const atom_ptr = sym.atom(self).?;
31873184
3188 const shdr_index = self.getDeclShdrIndex(decl_index, code);3185 const shdr_index = self.getDeclShdrIndex(decl_index, code);
...@@ -3340,7 +3337,7 @@ pub fn updateDecl(...@@ -3340,7 +3337,7 @@ pub fn updateDecl(
3340 const name = mod.intern_pool.stringToSlice(decl.name);3337 const name = mod.intern_pool.stringToSlice(decl.name);
3341 const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name);3338 const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name);
3342 const esym_index = try self.getGlobalSymbol(name, lib_name);3339 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;
3344 return;3341 return;
3345 }3342 }
33463343
...@@ -3401,7 +3398,7 @@ pub fn updateDecl(...@@ -3401,7 +3398,7 @@ pub fn updateDecl(
3401fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol.Index) !void {3398fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol.Index) !void {
3402 const gpa = self.base.allocator;3399 const gpa = self.base.allocator;
3403 const mod = self.base.options.module.?;3400 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
3406 var required_alignment: InternPool.Alignment = .none;3403 var required_alignment: InternPool.Alignment = .none;
3407 var code_buffer = std.ArrayList(u8).init(gpa);3404 var code_buffer = std.ArrayList(u8).init(gpa);
...@@ -3449,7 +3446,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol....@@ -3449,7 +3446,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol.
3449 const phdr_index = self.phdr_to_shdr_table.get(output_section_index).?;3446 const phdr_index = self.phdr_to_shdr_table.get(output_section_index).?;
3450 local_sym.name_offset = name_str_index;3447 local_sym.name_offset = name_str_index;
3451 local_sym.output_section_index = output_section_index;3448 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];
3453 local_esym.st_name = name_str_index;3450 local_esym.st_name = name_str_index;
3454 local_esym.st_info |= elf.STT_OBJECT;3451 local_esym.st_info |= elf.STT_OBJECT;
3455 local_esym.st_size = code.len;3452 local_esym.st_size = code.len;
...@@ -3519,8 +3516,8 @@ fn lowerConst(...@@ -3519,8 +3516,8 @@ fn lowerConst(
3519 var code_buffer = std.ArrayList(u8).init(gpa);3516 var code_buffer = std.ArrayList(u8).init(gpa);
3520 defer code_buffer.deinit();3517 defer code_buffer.deinit();
35213518
3522 const zig_module = self.file(self.zig_module_index.?).?.zig_module;3519 const zig_object = self.zigObjectPtr().?;
3523 const sym_index = try zig_module.addAtom(self);3520 const sym_index = try zig_object.addAtom(self);
35243521
3525 const res = try codegen.generateSymbol(&self.base, src_loc, tv, &code_buffer, .{3522 const res = try codegen.generateSymbol(&self.base, src_loc, tv, &code_buffer, .{
3526 .none = {},3523 .none = {},
...@@ -3537,7 +3534,7 @@ fn lowerConst(...@@ -3537,7 +3534,7 @@ fn lowerConst(
3537 const name_str_index = try self.strtab.insert(gpa, name);3534 const name_str_index = try self.strtab.insert(gpa, name);
3538 local_sym.name_offset = name_str_index;3535 local_sym.name_offset = name_str_index;
3539 local_sym.output_section_index = output_section_index;3536 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];
3541 local_esym.st_name = name_str_index;3538 local_esym.st_name = name_str_index;
3542 local_esym.st_info |= elf.STT_OBJECT;3539 local_esym.st_info |= elf.STT_OBJECT;
3543 local_esym.st_size = code.len;3540 local_esym.st_size = code.len;
...@@ -3579,7 +3576,7 @@ pub fn updateExports(...@@ -3579,7 +3576,7 @@ pub fn updateExports(
3579 defer tracy.end();3576 defer tracy.end();
35803577
3581 const gpa = self.base.allocator;3578 const gpa = self.base.allocator;
3582 const zig_module = self.file(self.zig_module_index.?).?.zig_module;3579 const zig_object = self.zigObjectPtr().?;
3583 const metadata = switch (exported) {3580 const metadata = switch (exported) {
3584 .decl_index => |decl_index| blk: {3581 .decl_index => |decl_index| blk: {
3585 _ = try self.getOrCreateMetadataForDecl(decl_index);3582 _ = try self.getOrCreateMetadataForDecl(decl_index);
...@@ -3603,8 +3600,8 @@ pub fn updateExports(...@@ -3603,8 +3600,8 @@ pub fn updateExports(
3603 };3600 };
3604 const sym_index = metadata.symbol_index;3601 const sym_index = metadata.symbol_index;
3605 const esym_index = self.symbol(sym_index).esym_index;3602 const esym_index = self.symbol(sym_index).esym_index;
3606 const esym = zig_module.local_esyms.items(.elf_sym)[esym_index];3603 const esym = zig_object.local_esyms.items(.elf_sym)[esym_index];
3607 const esym_shndx = zig_module.local_esyms.items(.shndx)[esym_index];3604 const esym_shndx = zig_object.local_esyms.items(.shndx)[esym_index];
36083605
3609 for (exports) |exp| {3606 for (exports) |exp| {
3610 if (exp.opts.section.unwrap()) |section_name| {3607 if (exp.opts.section.unwrap()) |section_name| {
...@@ -3638,24 +3635,24 @@ pub fn updateExports(...@@ -3638,24 +3635,24 @@ pub fn updateExports(
3638 const exp_name = mod.intern_pool.stringToSlice(exp.opts.name);3635 const exp_name = mod.intern_pool.stringToSlice(exp.opts.name);
3639 const name_off = try self.strtab.insert(gpa, exp_name);3636 const name_off = try self.strtab.insert(gpa, exp_name);
3640 const global_esym_index = if (metadata.@"export"(self, exp_name)) |exp_index| exp_index.* else blk: {3637 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);3638 const global_esym_index = try zig_object.addGlobalEsym(gpa);
3642 const lookup_gop = try zig_module.globals_lookup.getOrPut(gpa, name_off);3639 const lookup_gop = try zig_object.globals_lookup.getOrPut(gpa, name_off);
3643 const global_esym = zig_module.elfSym(global_esym_index);3640 const global_esym = zig_object.elfSym(global_esym_index);
3644 global_esym.st_name = name_off;3641 global_esym.st_name = name_off;
3645 lookup_gop.value_ptr.* = global_esym_index;3642 lookup_gop.value_ptr.* = global_esym_index;
3646 try metadata.exports.append(gpa, global_esym_index);3643 try metadata.exports.append(gpa, global_esym_index);
3647 const gop = try self.getOrPutGlobal(name_off);3644 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);
3649 break :blk global_esym_index;3646 break :blk global_esym_index;
3650 };3647 };
36513648
3652 const actual_esym_index = global_esym_index & ZigModule.symbol_mask;3649 const actual_esym_index = global_esym_index & ZigObject.symbol_mask;
3653 const global_esym = &zig_module.global_esyms.items(.elf_sym)[actual_esym_index];3650 const global_esym = &zig_object.global_esyms.items(.elf_sym)[actual_esym_index];
3654 global_esym.st_value = self.symbol(sym_index).value;3651 global_esym.st_value = self.symbol(sym_index).value;
3655 global_esym.st_shndx = esym.st_shndx;3652 global_esym.st_shndx = esym.st_shndx;
3656 global_esym.st_info = (stb_bits << 4) | stt_bits;3653 global_esym.st_info = (stb_bits << 4) | stt_bits;
3657 global_esym.st_name = name_off;3654 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;
3659 }3656 }
3660}3657}
36613658
...@@ -3683,20 +3680,20 @@ pub fn deleteDeclExport(...@@ -3683,20 +3680,20 @@ pub fn deleteDeclExport(
3683 if (self.llvm_object) |_| return;3680 if (self.llvm_object) |_| return;
3684 const metadata = self.decls.getPtr(decl_index) orelse return;3681 const metadata = self.decls.getPtr(decl_index) orelse return;
3685 const mod = self.base.options.module.?;3682 const mod = self.base.options.module.?;
3686 const zig_module = self.file(self.zig_module_index.?).?.zig_module;3683 const zig_object = self.zigObjectPtr().?;
3687 const exp_name = mod.intern_pool.stringToSlice(name);3684 const exp_name = mod.intern_pool.stringToSlice(name);
3688 const esym_index = metadata.@"export"(self, exp_name) orelse return;3685 const esym_index = metadata.@"export"(self, exp_name) orelse return;
3689 log.debug("deleting export '{s}'", .{exp_name});3686 log.debug("deleting export '{s}'", .{exp_name});
3690 const esym = &zig_module.global_esyms.items(.elf_sym)[esym_index.*];3687 const esym = &zig_object.global_esyms.items(.elf_sym)[esym_index.*];
3691 _ = zig_module.globals_lookup.remove(esym.st_name);3688 _ = zig_object.globals_lookup.remove(esym.st_name);
3692 const sym_index = self.resolver.get(esym.st_name).?;3689 const sym_index = self.resolver.get(esym.st_name).?;
3693 const sym = self.symbol(sym_index);3690 const sym = self.symbol(sym_index);
3694 if (sym.file_index == zig_module.index) {3691 if (sym.file_index == zig_object.index) {
3695 _ = self.resolver.swapRemove(esym.st_name);3692 _ = self.resolver.swapRemove(esym.st_name);
3696 sym.* = .{};3693 sym.* = .{};
3697 }3694 }
3698 esym.* = null_sym;3695 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;
3700}3697}
37013698
3702fn addLinkerDefinedSymbols(self: *Elf) !void {3699fn addLinkerDefinedSymbols(self: *Elf) !void {
...@@ -3917,8 +3914,8 @@ fn initSections(self: *Elf) !void {...@@ -3917,8 +3914,8 @@ fn initSections(self: *Elf) !void {
3917 const needs_rela_dyn = blk: {3914 const needs_rela_dyn = blk: {
3918 if (self.got.flags.needs_rela or self.got.flags.needs_tlsld or3915 if (self.got.flags.needs_rela or self.got.flags.needs_tlsld or
3919 self.zig_got.flags.needs_rela or self.copy_rel.symbols.items.len > 0) break :blk true;3916 self.zig_got.flags.needs_rela or self.copy_rel.symbols.items.len > 0) break :blk true;
3920 if (self.zig_module_index) |index| {3917 if (self.zigObjectPtr()) |zig_object| {
3921 if (self.file(index).?.zig_module.num_dynrelocs > 0) break :blk true;3918 if (zig_object.num_dynrelocs > 0) break :blk true;
3922 }3919 }
3923 for (self.objects.items) |index| {3920 for (self.objects.items) |index| {
3924 if (self.file(index).?.object.num_dynrelocs > 0) break :blk true;3921 if (self.file(index).?.object.num_dynrelocs > 0) break :blk true;
...@@ -4512,16 +4509,15 @@ fn sortShdrs(self: *Elf) !void {...@@ -4512,16 +4509,15 @@ fn sortShdrs(self: *Elf) !void {
4512 }4509 }
4513 }4510 }
45144511
4515 if (self.zig_module_index) |index| {4512 if (self.zigObjectPtr()) |zig_object| {
4516 const zig_module = self.file(index).?.zig_module;4513 for (zig_object.atoms.items) |atom_index| {
4517 for (zig_module.atoms.items) |atom_index| {
4518 const atom_ptr = self.atom(atom_index) orelse continue;4514 const atom_ptr = self.atom(atom_index) orelse continue;
4519 if (!atom_ptr.flags.alive) continue;4515 if (!atom_ptr.flags.alive) continue;
4520 const out_shndx = atom_ptr.outputShndx() orelse continue;4516 const out_shndx = atom_ptr.outputShndx() orelse continue;
4521 atom_ptr.output_section_index = backlinks[out_shndx];4517 atom_ptr.output_section_index = backlinks[out_shndx];
4522 }4518 }
45234519
4524 for (zig_module.locals()) |local_index| {4520 for (zig_object.locals()) |local_index| {
4525 const local = self.symbol(local_index);4521 const local = self.symbol(local_index);
4526 const atom_ptr = local.atom(self) orelse continue;4522 const atom_ptr = local.atom(self) orelse continue;
4527 if (!atom_ptr.flags.alive) continue;4523 if (!atom_ptr.flags.alive) continue;
...@@ -4529,11 +4525,11 @@ fn sortShdrs(self: *Elf) !void {...@@ -4529,11 +4525,11 @@ fn sortShdrs(self: *Elf) !void {
4529 local.output_section_index = backlinks[out_shndx];4525 local.output_section_index = backlinks[out_shndx];
4530 }4526 }
45314527
4532 for (zig_module.globals()) |global_index| {4528 for (zig_object.globals()) |global_index| {
4533 const global = self.symbol(global_index);4529 const global = self.symbol(global_index);
4534 const atom_ptr = global.atom(self) orelse continue;4530 const atom_ptr = global.atom(self) orelse continue;
4535 if (!atom_ptr.flags.alive) continue;4531 if (!atom_ptr.flags.alive) continue;
4536 if (global.file(self).?.index() != index) continue;4532 if (global.file(self).?.index() != zig_object.index) continue;
4537 const out_shndx = global.outputShndx() orelse continue;4533 const out_shndx = global.outputShndx() orelse continue;
4538 global.output_section_index = backlinks[out_shndx];4534 global.output_section_index = backlinks[out_shndx];
4539 }4535 }
...@@ -4599,8 +4595,8 @@ fn updateSectionSizes(self: *Elf) !void {...@@ -4599,8 +4595,8 @@ fn updateSectionSizes(self: *Elf) !void {
45994595
4600 if (self.rela_dyn_section_index) |shndx| {4596 if (self.rela_dyn_section_index) |shndx| {
4601 var num = self.got.numRela(self) + self.copy_rel.numRela() + self.zig_got.numRela();4597 var num = self.got.numRela(self) + self.copy_rel.numRela() + self.zig_got.numRela();
4602 if (self.zig_module_index) |index| {4598 if (self.zigObjectPtr()) |zig_object| {
4603 num += self.file(index).?.zig_module.num_dynrelocs;4599 num += zig_object.num_dynrelocs;
4604 }4600 }
4605 for (self.objects.items) |index| {4601 for (self.objects.items) |index| {
4606 num += self.file(index).?.object.num_dynrelocs;4602 num += self.file(index).?.object.num_dynrelocs;
...@@ -5079,11 +5075,10 @@ fn writeAtoms(self: *Elf) !void {...@@ -5079,11 +5075,10 @@ fn writeAtoms(self: *Elf) !void {
5079fn updateSymtabSize(self: *Elf) !void {5075fn updateSymtabSize(self: *Elf) !void {
5080 var sizes = SymtabSize{};5076 var sizes = SymtabSize{};
50815077
5082 if (self.zig_module_index) |index| {5078 if (self.zigObjectPtr()) |zig_object| {
5083 const zig_module = self.file(index).?.zig_module;5079 zig_object.updateSymtabSize(self);
5084 zig_module.updateSymtabSize(self);5080 sizes.nlocals += zig_object.output_symtab_size.nlocals;
5085 sizes.nlocals += zig_module.output_symtab_size.nlocals;5081 sizes.nglobals += zig_object.output_symtab_size.nglobals;
5086 sizes.nglobals += zig_module.output_symtab_size.nglobals;
5087 }5082 }
50885083
5089 for (self.objects.items) |index| {5084 for (self.objects.items) |index| {
...@@ -5299,11 +5294,10 @@ fn writeSymtab(self: *Elf) !void {...@@ -5299,11 +5294,10 @@ fn writeSymtab(self: *Elf) !void {
5299 .symtab = symtab,5294 .symtab = symtab,
5300 };5295 };
53015296
5302 if (self.zig_module_index) |index| {5297 if (self.zigObjectPtr()) |zig_object| {
5303 const zig_module = self.file(index).?.zig_module;5298 zig_object.writeSymtab(self, ctx);
5304 zig_module.writeSymtab(self, ctx);5299 ctx.ilocal += zig_object.output_symtab_size.nlocals;
5305 ctx.ilocal += zig_module.output_symtab_size.nlocals;5300 ctx.iglobal += zig_object.output_symtab_size.nglobals;
5306 ctx.iglobal += zig_module.output_symtab_size.nglobals;
5307 }5301 }
53085302
5309 for (self.objects.items) |index| {5303 for (self.objects.items) |index| {
...@@ -5863,7 +5857,7 @@ pub fn file(self: *Elf, index: File.Index) ?File {...@@ -5863,7 +5857,7 @@ pub fn file(self: *Elf, index: File.Index) ?File {
5863 return switch (tag) {5857 return switch (tag) {
5864 .null => null,5858 .null => null,
5865 .linker_defined => .{ .linker_defined = &self.files.items(.data)[index].linker_defined },5859 .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 },
5867 .object => .{ .object = &self.files.items(.data)[index].object },5861 .object => .{ .object = &self.files.items(.data)[index].object },
5868 .shared_object => .{ .shared_object = &self.files.items(.data)[index].shared_object },5862 .shared_object => .{ .shared_object = &self.files.items(.data)[index].shared_object },
5869 };5863 };
...@@ -5964,23 +5958,22 @@ pub fn getGlobalSymbol(self: *Elf, name: []const u8, lib_name: ?[]const u8) !u32...@@ -5964,23 +5958,22 @@ pub fn getGlobalSymbol(self: *Elf, name: []const u8, lib_name: ?[]const u8) !u32
5964 _ = lib_name;5958 _ = lib_name;
5965 const gpa = self.base.allocator;5959 const gpa = self.base.allocator;
5966 const off = try self.strtab.insert(gpa, name);5960 const off = try self.strtab.insert(gpa, name);
5967 const zig_module = self.file(self.zig_module_index.?).?.zig_module;5961 const zig_object = self.zigObjectPtr().?;
5968 const lookup_gop = try zig_module.globals_lookup.getOrPut(gpa, off);5962 const lookup_gop = try zig_object.globals_lookup.getOrPut(gpa, off);
5969 if (!lookup_gop.found_existing) {5963 if (!lookup_gop.found_existing) {
5970 const esym_index = try zig_module.addGlobalEsym(gpa);5964 const esym_index = try zig_object.addGlobalEsym(gpa);
5971 const esym = zig_module.elfSym(esym_index);5965 const esym = zig_object.elfSym(esym_index);
5972 esym.st_name = off;5966 esym.st_name = off;
5973 lookup_gop.value_ptr.* = esym_index;5967 lookup_gop.value_ptr.* = esym_index;
5974 const gop = try self.getOrPutGlobal(off);5968 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);
5976 }5970 }
5977 return lookup_gop.value_ptr.*;5971 return lookup_gop.value_ptr.*;
5978}5972}
59795973
5980pub fn zigModulePtr(self: *Elf) *ZigModule {5974pub fn zigObjectPtr(self: *Elf) ?*ZigObject {
5981 assert(self.zig_module_index != null);5975 const index = self.zig_object_index orelse return null;
5982 const file_ptr = self.file(self.zig_module_index.?).?;5976 return self.file(index).?.zig_object;
5983 return file_ptr.zig_module;
5984}5977}
59855978
5986const GetOrCreateComdatGroupOwnerResult = struct {5979const GetOrCreateComdatGroupOwnerResult = struct {
...@@ -6245,12 +6238,11 @@ fn fmtDumpState(...@@ -6245,12 +6238,11 @@ fn fmtDumpState(
6245 _ = unused_fmt_string;6238 _ = unused_fmt_string;
6246 _ = options;6239 _ = options;
62476240
6248 if (self.zig_module_index) |index| {6241 if (self.zigObjectPtr()) |zig_object| {
6249 const zig_module = self.file(index).?.zig_module;6242 try writer.print("zig_object({d}) : {s}\n", .{ zig_object.index, zig_object.path });
6250 try writer.print("zig_module({d}) : {s}\n", .{ index, zig_module.path });
6251 try writer.print("{}{}\n", .{6243 try writer.print("{}{}\n", .{
6252 zig_module.fmtAtoms(self),6244 zig_object.fmtAtoms(self),
6253 zig_module.fmtSymtab(self),6245 zig_object.fmtSymtab(self),
6254 });6246 });
6255 }6247 }
62566248
...@@ -6379,9 +6371,9 @@ const DeclMetadata = struct {...@@ -6379,9 +6371,9 @@ const DeclMetadata = struct {
6379 exports: std.ArrayListUnmanaged(Symbol.Index) = .{},6371 exports: std.ArrayListUnmanaged(Symbol.Index) = .{},
63806372
6381 fn @"export"(m: DeclMetadata, elf_file: *Elf, name: []const u8) ?*u32 {6373 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().?;
6383 for (m.exports.items) |*exp| {6375 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);
6385 if (mem.eql(u8, name, exp_name)) return exp;6377 if (mem.eql(u8, name, exp_name)) return exp;
6386 }6378 }
6387 return null;6379 return null;
...@@ -6491,4 +6483,4 @@ const TypedValue = @import("../TypedValue.zig");...@@ -6491,4 +6483,4 @@ const TypedValue = @import("../TypedValue.zig");
6491const Value = @import("../value.zig").Value;6483const Value = @import("../value.zig").Value;
6492const VerneedSection = synthetic_sections.VerneedSection;6484const VerneedSection = synthetic_sections.VerneedSection;
6493const ZigGotSection = synthetic_sections.ZigGotSection;6485const 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 {...@@ -52,7 +52,7 @@ pub fn file(self: Atom, elf_file: *Elf) ?File {
52pub fn inputShdr(self: Atom, elf_file: *Elf) Object.ElfShdr {52pub fn inputShdr(self: Atom, elf_file: *Elf) Object.ElfShdr {
53 return switch (self.file(elf_file).?) {53 return switch (self.file(elf_file).?) {
54 .object => |x| x.shdrs.items[self.input_section_index],54 .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),
56 else => unreachable,56 else => unreachable,
57 };57 };
58}58}
...@@ -270,14 +270,14 @@ pub fn free(self: *Atom, elf_file: *Elf) void {...@@ -270,14 +270,14 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
270 // TODO create relocs free list270 // TODO create relocs free list
271 self.freeRelocs(elf_file);271 self.freeRelocs(elf_file);
272 // TODO figure out how to free input section mappind in ZigModule272 // TODO figure out how to free input section mappind in ZigModule
273 // const zig_module = self.file(elf_file).?.zig_module;273 // const zig_object = elf_file.zigObjectPtr().?
274 // assert(zig_module.atoms.swapRemove(self.atom_index));274 // assert(zig_object.atoms.swapRemove(self.atom_index));
275 self.* = .{};275 self.* = .{};
276}276}
277277
278pub fn relocs(self: Atom, elf_file: *Elf) []align(1) const elf.Elf64_Rela {278pub fn relocs(self: Atom, elf_file: *Elf) []align(1) const elf.Elf64_Rela {
279 return switch (self.file(elf_file).?) {279 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,
281 .object => |x| x.getRelocs(self.relocs_section_index),281 .object => |x| x.getRelocs(self.relocs_section_index),
282 else => unreachable,282 else => unreachable,
283 };283 };
...@@ -298,17 +298,17 @@ pub fn markFdesDead(self: Atom, elf_file: *Elf) void {...@@ -298,17 +298,17 @@ pub fn markFdesDead(self: Atom, elf_file: *Elf) void {
298pub fn addReloc(self: Atom, elf_file: *Elf, reloc: elf.Elf64_Rela) !void {298pub fn addReloc(self: Atom, elf_file: *Elf, reloc: elf.Elf64_Rela) !void {
299 const gpa = elf_file.base.allocator;299 const gpa = elf_file.base.allocator;
300 const file_ptr = self.file(elf_file).?;300 const file_ptr = self.file(elf_file).?;
301 assert(file_ptr == .zig_module);301 assert(file_ptr == .zig_object);
302 const zig_module = file_ptr.zig_module;302 const zig_object = file_ptr.zig_object;
303 const rels = &zig_module.relocs.items[self.relocs_section_index];303 const rels = &zig_object.relocs.items[self.relocs_section_index];
304 try rels.append(gpa, reloc);304 try rels.append(gpa, reloc);
305}305}
306306
307pub fn freeRelocs(self: Atom, elf_file: *Elf) void {307pub fn freeRelocs(self: Atom, elf_file: *Elf) void {
308 const file_ptr = self.file(elf_file).?;308 const file_ptr = self.file(elf_file).?;
309 assert(file_ptr == .zig_module);309 assert(file_ptr == .zig_object);
310 const zig_module = file_ptr.zig_module;310 const zig_object = file_ptr.zig_object;
311 zig_module.relocs.items[self.relocs_section_index].clearRetainingCapacity();311 zig_object.relocs.items[self.relocs_section_index].clearRetainingCapacity();
312}312}
313313
314pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) bool {314pub 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...@@ -332,7 +332,7 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype
332 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;332 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
333333
334 const symbol_index = switch (file_ptr) {334 const symbol_index = switch (file_ptr) {
335 .zig_module => |x| x.symbol(rel.r_sym()),335 .zig_object => |x| x.symbol(rel.r_sym()),
336 .object => |x| x.symbols.items[rel.r_sym()],336 .object => |x| x.symbols.items[rel.r_sym()],
337 else => unreachable,337 else => unreachable,
338 };338 };
...@@ -690,7 +690,7 @@ fn reportUndefined(...@@ -690,7 +690,7 @@ fn reportUndefined(
690 undefs: anytype,690 undefs: anytype,
691) !void {691) !void {
692 const rel_esym = switch (self.file(elf_file).?) {692 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()).*,
694 .object => |x| x.symtab[rel.r_sym()],694 .object => |x| x.symtab[rel.r_sym()],
695 else => unreachable,695 else => unreachable,
696 };696 };
...@@ -724,7 +724,7 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) !void {...@@ -724,7 +724,7 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) !void {
724 if (r_type == elf.R_X86_64_NONE) continue;724 if (r_type == elf.R_X86_64_NONE) continue;
725725
726 const target = switch (file_ptr) {726 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())),
728 .object => |x| elf_file.symbol(x.symbols.items[rel.r_sym()]),728 .object => |x| elf_file.symbol(x.symbols.items[rel.r_sym()]),
729 else => unreachable,729 else => unreachable,
730 };730 };
...@@ -1004,7 +1004,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any...@@ -1004,7 +1004,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any
1004 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;1004 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
10051005
1006 const target_index = switch (file_ptr) {1006 const target_index = switch (file_ptr) {
1007 .zig_module => |x| x.symbol(rel.r_sym()),1007 .zig_object => |x| x.symbol(rel.r_sym()),
1008 .object => |x| x.symbols.items[rel.r_sym()],1008 .object => |x| x.symbols.items[rel.r_sym()],
1009 else => unreachable,1009 else => unreachable,
1010 };1010 };
src/link/Elf/Symbol.zig+1-2
...@@ -72,7 +72,7 @@ pub fn file(symbol: Symbol, elf_file: *Elf) ?File {...@@ -72,7 +72,7 @@ pub fn file(symbol: Symbol, elf_file: *Elf) ?File {
72pub fn elfSym(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym {72pub fn elfSym(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym {
73 const file_ptr = symbol.file(elf_file).?;73 const file_ptr = symbol.file(elf_file).?;
74 switch (file_ptr) {74 switch (file_ptr) {
75 .zig_module => |x| return x.elfSym(symbol.esym_index).*,75 .zig_object => |x| return x.elfSym(symbol.esym_index).*,
76 .linker_defined => |x| return x.symtab.items[symbol.esym_index],76 .linker_defined => |x| return x.symtab.items[symbol.esym_index],
77 inline else => |x| return x.symtab[symbol.esym_index],77 inline else => |x| return x.symtab[symbol.esym_index],
78 }78 }
...@@ -406,4 +406,3 @@ const PltSection = synthetic_sections.PltSection;...@@ -406,4 +406,3 @@ const PltSection = synthetic_sections.PltSection;
406const SharedObject = @import("SharedObject.zig");406const SharedObject = @import("SharedObject.zig");
407const Symbol = @This();407const Symbol = @This();
408const ZigGotSection = synthetic_sections.ZigGotSection;408const 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 @@...@@ -1,5 +1,5 @@
1pub const File = union(enum) {1pub const File = union(enum) {
2 zig_module: *ZigModule,2 zig_object: *ZigObject,
3 linker_defined: *LinkerDefined,3 linker_defined: *LinkerDefined,
4 object: *Object,4 object: *Object,
5 shared_object: *SharedObject,5 shared_object: *SharedObject,
...@@ -23,7 +23,7 @@ pub const File = union(enum) {...@@ -23,7 +23,7 @@ pub const File = union(enum) {
23 _ = unused_fmt_string;23 _ = unused_fmt_string;
24 _ = options;24 _ = options;
25 switch (file) {25 switch (file) {
26 .zig_module => |x| try writer.print("{s}", .{x.path}),26 .zig_object => |x| try writer.print("{s}", .{x.path}),
27 .linker_defined => try writer.writeAll("(linker defined)"),27 .linker_defined => try writer.writeAll("(linker defined)"),
28 .object => |x| try writer.print("{}", .{x.fmtPath()}),28 .object => |x| try writer.print("{}", .{x.fmtPath()}),
29 .shared_object => |x| try writer.writeAll(x.path),29 .shared_object => |x| try writer.writeAll(x.path),
...@@ -32,7 +32,7 @@ pub const File = union(enum) {...@@ -32,7 +32,7 @@ pub const File = union(enum) {
3232
33 pub fn isAlive(file: File) bool {33 pub fn isAlive(file: File) bool {
34 return switch (file) {34 return switch (file) {
35 .zig_module => true,35 .zig_object => true,
36 .linker_defined => true,36 .linker_defined => true,
37 inline else => |x| x.alive,37 inline else => |x| x.alive,
38 };38 };
...@@ -76,7 +76,7 @@ pub const File = union(enum) {...@@ -76,7 +76,7 @@ pub const File = union(enum) {
7676
77 pub fn setAlive(file: File) void {77 pub fn setAlive(file: File) void {
78 switch (file) {78 switch (file) {
79 .zig_module, .linker_defined => {},79 .zig_object, .linker_defined => {},
80 inline else => |x| x.alive = true,80 inline else => |x| x.alive = true,
81 }81 }
82 }82 }
...@@ -92,7 +92,7 @@ pub const File = union(enum) {...@@ -92,7 +92,7 @@ pub const File = union(enum) {
92 return switch (file) {92 return switch (file) {
93 .linker_defined => unreachable,93 .linker_defined => unreachable,
94 .shared_object => unreachable,94 .shared_object => unreachable,
95 .zig_module => |x| x.atoms.items,95 .zig_object => |x| x.atoms.items,
96 .object => |x| x.atoms.items,96 .object => |x| x.atoms.items,
97 };97 };
98 }98 }
...@@ -115,7 +115,7 @@ pub const File = union(enum) {...@@ -115,7 +115,7 @@ pub const File = union(enum) {
115115
116 pub const Entry = union(enum) {116 pub const Entry = union(enum) {
117 null: void,117 null: void,
118 zig_module: ZigModule,118 zig_object: ZigObject,
119 linker_defined: LinkerDefined,119 linker_defined: LinkerDefined,
120 object: Object,120 object: Object,
121 shared_object: SharedObject,121 shared_object: SharedObject,
...@@ -132,4 +132,4 @@ const LinkerDefined = @import("LinkerDefined.zig");...@@ -132,4 +132,4 @@ const LinkerDefined = @import("LinkerDefined.zig");
132const Object = @import("Object.zig");132const Object = @import("Object.zig");
133const SharedObject = @import("SharedObject.zig");133const SharedObject = @import("SharedObject.zig");
134const Symbol = @import("Symbol.zig");134const Symbol = @import("Symbol.zig");
135const ZigModule = @import("ZigModule.zig");135const ZigObject = @import("ZigObject.zig");