diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-09-10 08:41:13 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-09-10 08:41:13 +0200 |
| commit | a455b5692a657d01f07f5228a1abcb38f1abcc38 (patch) | |
| tree | de42b16f9c66e82554bd75cf1aade3dd9606646f /src/link | |
| parent | a6e9163284f75a9b251167eb7efb9b77169c5640 (diff) | |
| download | zig-a455b5692a657d01f07f5228a1abcb38f1abcc38.tar.gz zig-a455b5692a657d01f07f5228a1abcb38f1abcc38.zip | |
elf: create required linker-defined symbols
Diffstat (limited to 'src/link')
| -rw-r--r-- | src/link/Elf.zig | 92 | ||||
| -rw-r--r-- | src/link/Elf/LinkerDefined.zig | 16 | ||||
| -rw-r--r-- | src/link/Elf/Symbol.zig | 2 | ||||
| -rw-r--r-- | src/link/Elf/file.zig | 7 |
4 files changed, 99 insertions, 18 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 90b28d2e0c..e858a0ecb2 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -36,6 +36,7 @@ phdr_load_rw_index: ?u16 = null, entry_addr: ?u64 = null, page_size: u32, +default_sym_version: elf.Elf64_Versym, /// .shstrtab buffer shstrtab: StringTable(.strtab) = .{}, @@ -57,6 +58,23 @@ shstrtab_section_index: ?u16 = null, strtab_section_index: ?u16 = null, symtab_section_index: ?u16 = null, +// Linker-defined symbols +dynamic_index: ?Symbol.Index = null, +ehdr_start_index: ?Symbol.Index = null, +init_array_start_index: ?Symbol.Index = null, +init_array_end_index: ?Symbol.Index = null, +fini_array_start_index: ?Symbol.Index = null, +fini_array_end_index: ?Symbol.Index = null, +preinit_array_start_index: ?Symbol.Index = null, +preinit_array_end_index: ?Symbol.Index = null, +got_index: ?Symbol.Index = null, +plt_index: ?Symbol.Index = null, +end_index: ?Symbol.Index = null, +gnu_eh_frame_hdr_index: ?Symbol.Index = null, +dso_handle_index: ?Symbol.Index = null, +rela_iplt_start_index: ?Symbol.Index = null, +rela_iplt_end_index: ?Symbol.Index = null, + symbols: std.ArrayListUnmanaged(Symbol) = .{}, symbols_extra: std.ArrayListUnmanaged(u32) = .{}, resolver: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index) = .{}, @@ -188,6 +206,10 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf { .sparc64 => 0x2000, else => 0x1000, }; + const default_sym_version: elf.Elf64_Versym = if (options.output_mode == .Lib and options.link_mode == .Dynamic) + elf.VER_NDX_GLOBAL + else + elf.VER_NDX_LOCAL; var dwarf: ?Dwarf = if (!options.strip and options.module != null) Dwarf.init(gpa, &self.base, options.target) @@ -204,6 +226,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf { .dwarf = dwarf, .ptr_width = ptr_width, .page_size = page_size, + .default_sym_version = default_sym_version, }; const use_llvm = options.use_llvm; if (use_llvm) { @@ -987,11 +1010,12 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node // corresponds to the Zig source code. const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; - self.linker_defined_index = blk: { - const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); - self.files.set(index, .{ .linker_defined = .{ .index = index } }); - break :blk index; + const compiler_rt_path: ?[]const u8 = blk: { + if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; + if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; + break :blk null; }; + _ = compiler_rt_path; if (self.lazy_syms.getPtr(.none)) |metadata| { // 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 try dw.flushModule(module); } + if (self.linker_defined_index == null) { + const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); + self.files.set(index, .{ .linker_defined = .{ .index = index } }); + self.linker_defined_index = index; + } + + try self.addLinkerDefinedSymbols(); + + // Beyond this point, everything has been allocated a virtual address and we can resolve + // the relocations. { var it = self.relocs.iterator(); while (it.next()) |entry| { @@ -2682,6 +2716,54 @@ pub fn deleteDeclExport( sym_index.* = 0; } +fn addLinkerDefinedSymbols(self: *Elf) !void { + const linker_defined_index = self.linker_defined_index orelse return; + const linker_defined = self.file(linker_defined_index).?.linker_defined; + self.dynamic_index = try linker_defined.addGlobal("_DYNAMIC", self); + self.ehdr_start_index = try linker_defined.addGlobal("__ehdr_start", self); + self.init_array_start_index = try linker_defined.addGlobal("__init_array_start", self); + self.init_array_end_index = try linker_defined.addGlobal("__init_array_end", self); + self.fini_array_start_index = try linker_defined.addGlobal("__fini_array_start", self); + self.fini_array_end_index = try linker_defined.addGlobal("__fini_array_end", self); + self.preinit_array_start_index = try linker_defined.addGlobal("__preinit_array_start", self); + self.preinit_array_end_index = try linker_defined.addGlobal("__preinit_array_end", self); + self.got_index = try linker_defined.addGlobal("_GLOBAL_OFFSET_TABLE_", self); + self.plt_index = try linker_defined.addGlobal("_PROCEDURE_LINKAGE_TABLE_", self); + self.end_index = try linker_defined.addGlobal("_end", self); + + if (self.base.options.eh_frame_hdr) { + self.gnu_eh_frame_hdr_index = try linker_defined.addGlobal("__GNU_EH_FRAME_HDR", self); + } + + if (self.globalByName("__dso_handle")) |index| { + if (self.symbol(index).file(self) == null) + self.dso_handle_index = try linker_defined.addGlobal("__dso_handle", self); + } + + self.rela_iplt_start_index = try linker_defined.addGlobal("__rela_iplt_start", self); + self.rela_iplt_end_index = try linker_defined.addGlobal("__rela_iplt_end", self); + + // for (self.objects.items) |index| { + // const object = self.getFile(index).?.object; + // for (object.atoms.items) |atom_index| { + // if (self.getStartStopBasename(atom_index)) |name| { + // const gpa = self.base.allocator; + // try self.start_stop_indexes.ensureUnusedCapacity(gpa, 2); + + // const start = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name}); + // defer gpa.free(start); + // const stop = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name}); + // defer gpa.free(stop); + + // self.start_stop_indexes.appendAssumeCapacity(try internal.addSyntheticGlobal(start, self)); + // self.start_stop_indexes.appendAssumeCapacity(try internal.addSyntheticGlobal(stop, self)); + // } + // } + // } + + linker_defined.resolveSymbols(self); +} + fn updateSymtabSize(self: *Elf) !void { var sizes = SymtabSize{}; @@ -3193,7 +3275,7 @@ pub fn getOrPutGlobal(self: *Elf, name_off: u32) !GetOrPutGlobalResult { }; } -pub fn getGlobalByName(self: *Elf, name: []const u8) ?Symbol.Index { +pub fn globalByName(self: *Elf, name: []const u8) ?Symbol.Index { const name_off = self.strtab.getOffset(name) orelse return null; return self.resolver.get(name_off); } diff --git a/src/link/Elf/LinkerDefined.zig b/src/link/Elf/LinkerDefined.zig index 99125a9eb6..9bfff35302 100644 --- a/src/link/Elf/LinkerDefined.zig +++ b/src/link/Elf/LinkerDefined.zig @@ -22,7 +22,7 @@ pub fn addGlobal(self: *LinkerDefined, name: [:0]const u8, elf_file: *Elf) !u32 .st_value = 0, .st_size = 0, }); - const off = try elf_file.internString("{s}", .{name}); + const off = try elf_file.strtab.insert(gpa, name); const gop = try elf_file.getOrPutGlobal(off); self.symbols.addOneAssumeCapacity().* = gop.index; return gop.index; @@ -37,14 +37,12 @@ pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) void { const global = elf_file.symbol(index); if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) { - global.* = .{ - .value = 0, - .name = global.name, - .atom = 0, - .file = self.index, - .sym_idx = sym_idx, - .ver_idx = elf_file.default_sym_version, - }; + global.value = 0; + global.name_offset = global.name_offset; + global.atom_index = 0; + global.file_index = self.index; + global.esym_index = sym_idx; + global.version_index = elf_file.default_sym_version; } } } diff --git a/src/link/Elf/Symbol.zig b/src/link/Elf/Symbol.zig index be177922a8..322e7609eb 100644 --- a/src/link/Elf/Symbol.zig +++ b/src/link/Elf/Symbol.zig @@ -81,7 +81,7 @@ pub fn symbolRank(symbol: Symbol, elf_file: *Elf) u32 { // .object => |x| !x.alive, else => false, }; - return file_ptr.symbolRank(sym, in_archive); + return file_ptr.symbolRank(sym.*, in_archive); } pub fn address(symbol: Symbol, opts: struct { diff --git a/src/link/Elf/file.zig b/src/link/Elf/file.zig index 82d2d89c29..823ae5209e 100644 --- a/src/link/Elf/file.zig +++ b/src/link/Elf/file.zig @@ -25,8 +25,8 @@ pub const File = union(enum) { switch (file) { .zig_module => try writer.writeAll("(zig module)"), .linker_defined => try writer.writeAll("(linker defined)"), - .object => |x| try writer.print("{}", .{x.fmtPath()}), - .shared_object => |x| try writer.writeAll(x.path), + // .object => |x| try writer.print("{}", .{x.fmtPath()}), + // .shared_object => |x| try writer.writeAll(x.path), } } @@ -62,7 +62,8 @@ pub const File = union(enum) { pub fn symbolRank(file: File, sym: elf.Elf64_Sym, in_archive: bool) u32 { const base: u3 = blk: { if (sym.st_shndx == elf.SHN_COMMON) break :blk if (in_archive) 6 else 5; - if (file == .shared or in_archive) break :blk switch (sym.st_bind()) { + // if (file == .shared or in_archive) break :blk switch (sym.st_bind()) { + if (in_archive) break :blk switch (sym.st_bind()) { elf.STB_GLOBAL => 3, else => 4, }; |
