authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-10 08:41:13+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-10 08:41:13+02:00
loga455b5692a657d01f07f5228a1abcb38f1abcc38
treede42b16f9c66e82554bd75cf1aade3dd9606646f
parenta6e9163284f75a9b251167eb7efb9b77169c5640

elf: create required linker-defined symbols


4 files changed, 99 insertions(+), 18 deletions(-)

src/link/Elf.zig+87-5
...@@ -36,6 +36,7 @@ phdr_load_rw_index: ?u16 = null,...@@ -36,6 +36,7 @@ phdr_load_rw_index: ?u16 = null,
3636
37entry_addr: ?u64 = null,37entry_addr: ?u64 = null,
38page_size: u32,38page_size: u32,
39default_sym_version: elf.Elf64_Versym,
3940
40/// .shstrtab buffer41/// .shstrtab buffer
41shstrtab: StringTable(.strtab) = .{},42shstrtab: StringTable(.strtab) = .{},
...@@ -57,6 +58,23 @@ shstrtab_section_index: ?u16 = null,...@@ -57,6 +58,23 @@ shstrtab_section_index: ?u16 = null,
57strtab_section_index: ?u16 = null,58strtab_section_index: ?u16 = null,
58symtab_section_index: ?u16 = null,59symtab_section_index: ?u16 = null,
5960
61// Linker-defined symbols
62dynamic_index: ?Symbol.Index = null,
63ehdr_start_index: ?Symbol.Index = null,
64init_array_start_index: ?Symbol.Index = null,
65init_array_end_index: ?Symbol.Index = null,
66fini_array_start_index: ?Symbol.Index = null,
67fini_array_end_index: ?Symbol.Index = null,
68preinit_array_start_index: ?Symbol.Index = null,
69preinit_array_end_index: ?Symbol.Index = null,
70got_index: ?Symbol.Index = null,
71plt_index: ?Symbol.Index = null,
72end_index: ?Symbol.Index = null,
73gnu_eh_frame_hdr_index: ?Symbol.Index = null,
74dso_handle_index: ?Symbol.Index = null,
75rela_iplt_start_index: ?Symbol.Index = null,
76rela_iplt_end_index: ?Symbol.Index = null,
77
60symbols: std.ArrayListUnmanaged(Symbol) = .{},78symbols: std.ArrayListUnmanaged(Symbol) = .{},
61symbols_extra: std.ArrayListUnmanaged(u32) = .{},79symbols_extra: std.ArrayListUnmanaged(u32) = .{},
62resolver: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index) = .{},80resolver: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index) = .{},
...@@ -188,6 +206,10 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {...@@ -188,6 +206,10 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {
188 .sparc64 => 0x2000,206 .sparc64 => 0x2000,
189 else => 0x1000,207 else => 0x1000,
190 };208 };
209 const default_sym_version: elf.Elf64_Versym = if (options.output_mode == .Lib and options.link_mode == .Dynamic)
210 elf.VER_NDX_GLOBAL
211 else
212 elf.VER_NDX_LOCAL;
191213
192 var dwarf: ?Dwarf = if (!options.strip and options.module != null)214 var dwarf: ?Dwarf = if (!options.strip and options.module != null)
193 Dwarf.init(gpa, &self.base, options.target)215 Dwarf.init(gpa, &self.base, options.target)
...@@ -204,6 +226,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {...@@ -204,6 +226,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {
204 .dwarf = dwarf,226 .dwarf = dwarf,
205 .ptr_width = ptr_width,227 .ptr_width = ptr_width,
206 .page_size = page_size,228 .page_size = page_size,
229 .default_sym_version = default_sym_version,
207 };230 };
208 const use_llvm = options.use_llvm;231 const use_llvm = options.use_llvm;
209 if (use_llvm) {232 if (use_llvm) {
...@@ -987,11 +1010,12 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -987,11 +1010,12 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
987 // corresponds to the Zig source code.1010 // corresponds to the Zig source code.
988 const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;1011 const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;
9891012
990 self.linker_defined_index = blk: {1013 const compiler_rt_path: ?[]const u8 = blk: {
991 const index = @as(File.Index, @intCast(try self.files.addOne(gpa)));1014 if (comp.compiler_rt_lib) |x| break :blk x.full_object_path;
992 self.files.set(index, .{ .linker_defined = .{ .index = index } });1015 if (comp.compiler_rt_obj) |x| break :blk x.full_object_path;
993 break :blk index;1016 break :blk null;
994 };1017 };
1018 _ = compiler_rt_path;
9951019
996 if (self.lazy_syms.getPtr(.none)) |metadata| {1020 if (self.lazy_syms.getPtr(.none)) |metadata| {
997 // Most lazy symbols can be updated on first use, but1021 // Most lazy symbols can be updated on first use, but
...@@ -1023,6 +1047,16 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1023,6 +1047,16 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1023 try dw.flushModule(module);1047 try dw.flushModule(module);
1024 }1048 }
10251049
1050 if (self.linker_defined_index == null) {
1051 const index = @as(File.Index, @intCast(try self.files.addOne(gpa)));
1052 self.files.set(index, .{ .linker_defined = .{ .index = index } });
1053 self.linker_defined_index = index;
1054 }
1055
1056 try self.addLinkerDefinedSymbols();
1057
1058 // Beyond this point, everything has been allocated a virtual address and we can resolve
1059 // the relocations.
1026 {1060 {
1027 var it = self.relocs.iterator();1061 var it = self.relocs.iterator();
1028 while (it.next()) |entry| {1062 while (it.next()) |entry| {
...@@ -2682,6 +2716,54 @@ pub fn deleteDeclExport(...@@ -2682,6 +2716,54 @@ pub fn deleteDeclExport(
2682 sym_index.* = 0;2716 sym_index.* = 0;
2683}2717}
26842718
2719fn addLinkerDefinedSymbols(self: *Elf) !void {
2720 const linker_defined_index = self.linker_defined_index orelse return;
2721 const linker_defined = self.file(linker_defined_index).?.linker_defined;
2722 self.dynamic_index = try linker_defined.addGlobal("_DYNAMIC", self);
2723 self.ehdr_start_index = try linker_defined.addGlobal("__ehdr_start", self);
2724 self.init_array_start_index = try linker_defined.addGlobal("__init_array_start", self);
2725 self.init_array_end_index = try linker_defined.addGlobal("__init_array_end", self);
2726 self.fini_array_start_index = try linker_defined.addGlobal("__fini_array_start", self);
2727 self.fini_array_end_index = try linker_defined.addGlobal("__fini_array_end", self);
2728 self.preinit_array_start_index = try linker_defined.addGlobal("__preinit_array_start", self);
2729 self.preinit_array_end_index = try linker_defined.addGlobal("__preinit_array_end", self);
2730 self.got_index = try linker_defined.addGlobal("_GLOBAL_OFFSET_TABLE_", self);
2731 self.plt_index = try linker_defined.addGlobal("_PROCEDURE_LINKAGE_TABLE_", self);
2732 self.end_index = try linker_defined.addGlobal("_end", self);
2733
2734 if (self.base.options.eh_frame_hdr) {
2735 self.gnu_eh_frame_hdr_index = try linker_defined.addGlobal("__GNU_EH_FRAME_HDR", self);
2736 }
2737
2738 if (self.globalByName("__dso_handle")) |index| {
2739 if (self.symbol(index).file(self) == null)
2740 self.dso_handle_index = try linker_defined.addGlobal("__dso_handle", self);
2741 }
2742
2743 self.rela_iplt_start_index = try linker_defined.addGlobal("__rela_iplt_start", self);
2744 self.rela_iplt_end_index = try linker_defined.addGlobal("__rela_iplt_end", self);
2745
2746 // for (self.objects.items) |index| {
2747 // const object = self.getFile(index).?.object;
2748 // for (object.atoms.items) |atom_index| {
2749 // if (self.getStartStopBasename(atom_index)) |name| {
2750 // const gpa = self.base.allocator;
2751 // try self.start_stop_indexes.ensureUnusedCapacity(gpa, 2);
2752
2753 // const start = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name});
2754 // defer gpa.free(start);
2755 // const stop = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name});
2756 // defer gpa.free(stop);
2757
2758 // self.start_stop_indexes.appendAssumeCapacity(try internal.addSyntheticGlobal(start, self));
2759 // self.start_stop_indexes.appendAssumeCapacity(try internal.addSyntheticGlobal(stop, self));
2760 // }
2761 // }
2762 // }
2763
2764 linker_defined.resolveSymbols(self);
2765}
2766
2685fn updateSymtabSize(self: *Elf) !void {2767fn updateSymtabSize(self: *Elf) !void {
2686 var sizes = SymtabSize{};2768 var sizes = SymtabSize{};
26872769
...@@ -3193,7 +3275,7 @@ pub fn getOrPutGlobal(self: *Elf, name_off: u32) !GetOrPutGlobalResult {...@@ -3193,7 +3275,7 @@ pub fn getOrPutGlobal(self: *Elf, name_off: u32) !GetOrPutGlobalResult {
3193 };3275 };
3194}3276}
31953277
3196pub fn getGlobalByName(self: *Elf, name: []const u8) ?Symbol.Index {3278pub fn globalByName(self: *Elf, name: []const u8) ?Symbol.Index {
3197 const name_off = self.strtab.getOffset(name) orelse return null;3279 const name_off = self.strtab.getOffset(name) orelse return null;
3198 return self.resolver.get(name_off);3280 return self.resolver.get(name_off);
3199}3281}
src/link/Elf/LinkerDefined.zig+7-9
...@@ -22,7 +22,7 @@ pub fn addGlobal(self: *LinkerDefined, name: [:0]const u8, elf_file: *Elf) !u32...@@ -22,7 +22,7 @@ pub fn addGlobal(self: *LinkerDefined, name: [:0]const u8, elf_file: *Elf) !u32
22 .st_value = 0,22 .st_value = 0,
23 .st_size = 0,23 .st_size = 0,
24 });24 });
25 const off = try elf_file.internString("{s}", .{name});25 const off = try elf_file.strtab.insert(gpa, name);
26 const gop = try elf_file.getOrPutGlobal(off);26 const gop = try elf_file.getOrPutGlobal(off);
27 self.symbols.addOneAssumeCapacity().* = gop.index;27 self.symbols.addOneAssumeCapacity().* = gop.index;
28 return gop.index;28 return gop.index;
...@@ -37,14 +37,12 @@ pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) void {...@@ -37,14 +37,12 @@ pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) void {
3737
38 const global = elf_file.symbol(index);38 const global = elf_file.symbol(index);
39 if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) {39 if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) {
40 global.* = .{40 global.value = 0;
41 .value = 0,41 global.name_offset = global.name_offset;
42 .name = global.name,42 global.atom_index = 0;
43 .atom = 0,43 global.file_index = self.index;
44 .file = self.index,44 global.esym_index = sym_idx;
45 .sym_idx = sym_idx,45 global.version_index = elf_file.default_sym_version;
46 .ver_idx = elf_file.default_sym_version,
47 };
48 }46 }
49 }47 }
50}48}
src/link/Elf/Symbol.zig+1-1
...@@ -81,7 +81,7 @@ pub fn symbolRank(symbol: Symbol, elf_file: *Elf) u32 {...@@ -81,7 +81,7 @@ pub fn symbolRank(symbol: Symbol, elf_file: *Elf) u32 {
81 // .object => |x| !x.alive,81 // .object => |x| !x.alive,
82 else => false,82 else => false,
83 };83 };
84 return file_ptr.symbolRank(sym, in_archive);84 return file_ptr.symbolRank(sym.*, in_archive);
85}85}
8686
87pub fn address(symbol: Symbol, opts: struct {87pub fn address(symbol: Symbol, opts: struct {
src/link/Elf/file.zig+4-3
...@@ -25,8 +25,8 @@ pub const File = union(enum) {...@@ -25,8 +25,8 @@ pub const File = union(enum) {
25 switch (file) {25 switch (file) {
26 .zig_module => try writer.writeAll("(zig module)"),26 .zig_module => try writer.writeAll("(zig module)"),
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),
30 }30 }
31 }31 }
3232
...@@ -62,7 +62,8 @@ pub const File = union(enum) {...@@ -62,7 +62,8 @@ pub const File = union(enum) {
62 pub fn symbolRank(file: File, sym: elf.Elf64_Sym, in_archive: bool) u32 {62 pub fn symbolRank(file: File, sym: elf.Elf64_Sym, in_archive: bool) u32 {
63 const base: u3 = blk: {63 const base: u3 = blk: {
64 if (sym.st_shndx == elf.SHN_COMMON) break :blk if (in_archive) 6 else 5;64 if (sym.st_shndx == elf.SHN_COMMON) break :blk if (in_archive) 6 else 5;
65 if (file == .shared or in_archive) break :blk switch (sym.st_bind()) {65 // if (file == .shared or in_archive) break :blk switch (sym.st_bind()) {
66 if (in_archive) break :blk switch (sym.st_bind()) {
66 elf.STB_GLOBAL => 3,67 elf.STB_GLOBAL => 3,
67 else => 4,68 else => 4,
68 };69 };