aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2023-09-10 08:41:13 +0200
committerJakub Konka <kubkon@jakubkonka.com>2023-09-10 08:41:13 +0200
commita455b5692a657d01f07f5228a1abcb38f1abcc38 (patch)
treede42b16f9c66e82554bd75cf1aade3dd9606646f /src
parenta6e9163284f75a9b251167eb7efb9b77169c5640 (diff)
downloadzig-a455b5692a657d01f07f5228a1abcb38f1abcc38.tar.gz
zig-a455b5692a657d01f07f5228a1abcb38f1abcc38.zip
elf: create required linker-defined symbols
Diffstat (limited to 'src')
-rw-r--r--src/link/Elf.zig92
-rw-r--r--src/link/Elf/LinkerDefined.zig16
-rw-r--r--src/link/Elf/Symbol.zig2
-rw-r--r--src/link/Elf/file.zig7
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,
};