aboutsummaryrefslogtreecommitdiff
path: root/src/link/Elf
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2024-07-28 23:19:35 +0200
committerJakub Konka <kubkon@jakubkonka.com>2024-07-30 10:03:11 +0200
commit5ceac8ebbae5fedc56c74e2b3d4918742089ec45 (patch)
tree6bc07389c720b74d50e6a595190c4dc4a965df4a /src/link/Elf
parentef7bbcd80fec680b527795dd85bc294b3bf6cbbd (diff)
downloadzig-5ceac8ebbae5fedc56c74e2b3d4918742089ec45.tar.gz
zig-5ceac8ebbae5fedc56c74e2b3d4918742089ec45.zip
elf: move initializing and allocating linker-defined symbols into LinkerDefined
Diffstat (limited to 'src/link/Elf')
-rw-r--r--src/link/Elf/LinkerDefined.zig217
-rw-r--r--src/link/Elf/synthetic_sections.zig2
2 files changed, 217 insertions, 2 deletions
diff --git a/src/link/Elf/LinkerDefined.zig b/src/link/Elf/LinkerDefined.zig
index 6009f446a9..dbca64d325 100644
--- a/src/link/Elf/LinkerDefined.zig
+++ b/src/link/Elf/LinkerDefined.zig
@@ -4,12 +4,31 @@ symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
strtab: std.ArrayListUnmanaged(u8) = .{},
symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
+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,
+global_pointer_index: ?Symbol.Index = null,
+start_stop_indexes: std.ArrayListUnmanaged(u32) = .{},
+
output_symtab_ctx: Elf.SymtabCtx = .{},
pub fn deinit(self: *LinkerDefined, allocator: Allocator) void {
self.symtab.deinit(allocator);
self.strtab.deinit(allocator);
self.symbols.deinit(allocator);
+ self.start_stop_indexes.deinit(allocator);
}
pub fn init(self: *LinkerDefined, allocator: Allocator) !void {
@@ -17,7 +36,55 @@ pub fn init(self: *LinkerDefined, allocator: Allocator) !void {
try self.strtab.append(allocator, 0);
}
-pub fn addGlobal(self: *LinkerDefined, name: [:0]const u8, elf_file: *Elf) !u32 {
+pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
+ const gpa = elf_file.base.comp.gpa;
+
+ self.dynamic_index = try self.addGlobal("_DYNAMIC", elf_file);
+ self.ehdr_start_index = try self.addGlobal("__ehdr_start", elf_file);
+ self.init_array_start_index = try self.addGlobal("__init_array_start", elf_file);
+ self.init_array_end_index = try self.addGlobal("__init_array_end", elf_file);
+ self.fini_array_start_index = try self.addGlobal("__fini_array_start", elf_file);
+ self.fini_array_end_index = try self.addGlobal("__fini_array_end", elf_file);
+ self.preinit_array_start_index = try self.addGlobal("__preinit_array_start", elf_file);
+ self.preinit_array_end_index = try self.addGlobal("__preinit_array_end", elf_file);
+ self.got_index = try self.addGlobal("_GLOBAL_OFFSET_TABLE_", elf_file);
+ self.plt_index = try self.addGlobal("_PROCEDURE_LINKAGE_TABLE_", elf_file);
+ self.end_index = try self.addGlobal("_end", elf_file);
+
+ if (elf_file.base.comp.link_eh_frame_hdr) {
+ self.gnu_eh_frame_hdr_index = try self.addGlobal("__GNU_EH_FRAME_HDR", elf_file);
+ }
+
+ if (elf_file.globalByName("__dso_handle")) |index| {
+ if (elf_file.symbol(index).file(elf_file) == null)
+ self.dso_handle_index = try self.addGlobal("__dso_handle", elf_file);
+ }
+
+ self.rela_iplt_start_index = try self.addGlobal("__rela_iplt_start", elf_file);
+ self.rela_iplt_end_index = try self.addGlobal("__rela_iplt_end", elf_file);
+
+ for (elf_file.shdrs.items) |shdr| {
+ if (elf_file.getStartStopBasename(shdr)) |name| {
+ 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 self.addGlobal(start, elf_file));
+ self.start_stop_indexes.appendAssumeCapacity(try self.addGlobal(stop, elf_file));
+ }
+ }
+
+ if (elf_file.getTarget().cpu.arch.isRISCV() and elf_file.isEffectivelyDynLib()) {
+ self.global_pointer_index = try self.addGlobal("__global_pointer$", elf_file);
+ }
+
+ self.resolveSymbols(elf_file);
+}
+
+fn addGlobal(self: *LinkerDefined, name: [:0]const u8, elf_file: *Elf) !u32 {
const comp = elf_file.base.comp;
const gpa = comp.gpa;
try self.symtab.ensureUnusedCapacity(gpa, 1);
@@ -55,6 +122,154 @@ pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) void {
}
}
+pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
+ const comp = elf_file.base.comp;
+ const link_mode = comp.config.link_mode;
+
+ // _DYNAMIC
+ if (elf_file.dynamic_section_index) |shndx| {
+ const shdr = &elf_file.shdrs.items[shndx];
+ const symbol_ptr = elf_file.symbol(self.dynamic_index.?);
+ symbol_ptr.value = @intCast(shdr.sh_addr);
+ symbol_ptr.output_section_index = shndx;
+ }
+
+ // __ehdr_start
+ {
+ const symbol_ptr = elf_file.symbol(self.ehdr_start_index.?);
+ symbol_ptr.value = @intCast(elf_file.image_base);
+ symbol_ptr.output_section_index = 1;
+ }
+
+ // __init_array_start, __init_array_end
+ if (elf_file.sectionByName(".init_array")) |shndx| {
+ const start_sym = elf_file.symbol(self.init_array_start_index.?);
+ const end_sym = elf_file.symbol(self.init_array_end_index.?);
+ const shdr = &elf_file.shdrs.items[shndx];
+ start_sym.output_section_index = shndx;
+ start_sym.value = @intCast(shdr.sh_addr);
+ end_sym.output_section_index = shndx;
+ end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size);
+ }
+
+ // __fini_array_start, __fini_array_end
+ if (elf_file.sectionByName(".fini_array")) |shndx| {
+ const start_sym = elf_file.symbol(self.fini_array_start_index.?);
+ const end_sym = elf_file.symbol(self.fini_array_end_index.?);
+ const shdr = &elf_file.shdrs.items[shndx];
+ start_sym.output_section_index = shndx;
+ start_sym.value = @intCast(shdr.sh_addr);
+ end_sym.output_section_index = shndx;
+ end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size);
+ }
+
+ // __preinit_array_start, __preinit_array_end
+ if (elf_file.sectionByName(".preinit_array")) |shndx| {
+ const start_sym = elf_file.symbol(self.preinit_array_start_index.?);
+ const end_sym = elf_file.symbol(self.preinit_array_end_index.?);
+ const shdr = &elf_file.shdrs.items[shndx];
+ start_sym.output_section_index = shndx;
+ start_sym.value = @intCast(shdr.sh_addr);
+ end_sym.output_section_index = shndx;
+ end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size);
+ }
+
+ // _GLOBAL_OFFSET_TABLE_
+ if (elf_file.getTarget().cpu.arch == .x86_64) {
+ if (elf_file.got_plt_section_index) |shndx| {
+ const shdr = elf_file.shdrs.items[shndx];
+ const sym = elf_file.symbol(self.got_index.?);
+ sym.value = @intCast(shdr.sh_addr);
+ sym.output_section_index = shndx;
+ }
+ } else {
+ if (elf_file.got_section_index) |shndx| {
+ const shdr = elf_file.shdrs.items[shndx];
+ const sym = elf_file.symbol(self.got_index.?);
+ sym.value = @intCast(shdr.sh_addr);
+ sym.output_section_index = shndx;
+ }
+ }
+
+ // _PROCEDURE_LINKAGE_TABLE_
+ if (elf_file.plt_section_index) |shndx| {
+ const shdr = &elf_file.shdrs.items[shndx];
+ const symbol_ptr = elf_file.symbol(self.plt_index.?);
+ symbol_ptr.value = @intCast(shdr.sh_addr);
+ symbol_ptr.output_section_index = shndx;
+ }
+
+ // __dso_handle
+ if (self.dso_handle_index) |index| {
+ const shdr = &elf_file.shdrs.items[1];
+ const symbol_ptr = elf_file.symbol(index);
+ symbol_ptr.value = @intCast(shdr.sh_addr);
+ symbol_ptr.output_section_index = 0;
+ }
+
+ // __GNU_EH_FRAME_HDR
+ if (elf_file.eh_frame_hdr_section_index) |shndx| {
+ const shdr = &elf_file.shdrs.items[shndx];
+ const symbol_ptr = elf_file.symbol(self.gnu_eh_frame_hdr_index.?);
+ symbol_ptr.value = @intCast(shdr.sh_addr);
+ symbol_ptr.output_section_index = shndx;
+ }
+
+ // __rela_iplt_start, __rela_iplt_end
+ if (elf_file.rela_dyn_section_index) |shndx| blk: {
+ if (link_mode != .static or comp.config.pie) break :blk;
+ const shdr = &elf_file.shdrs.items[shndx];
+ const end_addr = shdr.sh_addr + shdr.sh_size;
+ const start_addr = end_addr - elf_file.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela);
+ const start_sym = elf_file.symbol(self.rela_iplt_start_index.?);
+ const end_sym = elf_file.symbol(self.rela_iplt_end_index.?);
+ start_sym.value = @intCast(start_addr);
+ start_sym.output_section_index = shndx;
+ end_sym.value = @intCast(end_addr);
+ end_sym.output_section_index = shndx;
+ }
+
+ // _end
+ {
+ const end_symbol = elf_file.symbol(self.end_index.?);
+ for (elf_file.shdrs.items, 0..) |shdr, shndx| {
+ if (shdr.sh_flags & elf.SHF_ALLOC != 0) {
+ end_symbol.value = @intCast(shdr.sh_addr + shdr.sh_size);
+ end_symbol.output_section_index = @intCast(shndx);
+ }
+ }
+ }
+
+ // __start_*, __stop_*
+ {
+ var index: usize = 0;
+ while (index < self.start_stop_indexes.items.len) : (index += 2) {
+ const start = elf_file.symbol(self.start_stop_indexes.items[index]);
+ const name = start.name(elf_file);
+ const stop = elf_file.symbol(self.start_stop_indexes.items[index + 1]);
+ const shndx = elf_file.sectionByName(name["__start_".len..]).?;
+ const shdr = &elf_file.shdrs.items[shndx];
+ start.value = @intCast(shdr.sh_addr);
+ start.output_section_index = shndx;
+ stop.value = @intCast(shdr.sh_addr + shdr.sh_size);
+ stop.output_section_index = shndx;
+ }
+ }
+
+ // __global_pointer$
+ if (self.global_pointer_index) |index| {
+ const sym = elf_file.symbol(index);
+ if (elf_file.sectionByName(".sdata")) |shndx| {
+ const shdr = elf_file.shdrs.items[shndx];
+ sym.value = @intCast(shdr.sh_addr + 0x800);
+ sym.output_section_index = shndx;
+ } else {
+ sym.value = 0;
+ sym.output_section_index = 0;
+ }
+ }
+}
+
pub fn globals(self: LinkerDefined) []const Symbol.Index {
return self.symbols.items;
}
diff --git a/src/link/Elf/synthetic_sections.zig b/src/link/Elf/synthetic_sections.zig
index 872356be82..c5c2359890 100644
--- a/src/link/Elf/synthetic_sections.zig
+++ b/src/link/Elf/synthetic_sections.zig
@@ -1075,7 +1075,7 @@ pub const GotPltSection = struct {
_ = got_plt;
{
// [0]: _DYNAMIC
- const symbol = elf_file.symbol(elf_file.dynamic_index.?);
+ const symbol = elf_file.symbol(elf_file.linkerDefinedPtr().?.dynamic_index.?);
try writer.writeInt(u64, @intCast(symbol.address(.{}, elf_file)), .little);
}
// [1]: 0x0