diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-07-28 23:19:35 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-07-30 10:03:11 +0200 |
| commit | 5ceac8ebbae5fedc56c74e2b3d4918742089ec45 (patch) | |
| tree | 6bc07389c720b74d50e6a595190c4dc4a965df4a /src/link/Elf | |
| parent | ef7bbcd80fec680b527795dd85bc294b3bf6cbbd (diff) | |
| download | zig-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.zig | 217 | ||||
| -rw-r--r-- | src/link/Elf/synthetic_sections.zig | 2 |
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 |
