mirror of
https://github.com/ziglang/zig.git
synced 2026-02-07 06:57:13 +00:00
elf: start-stop resolution has to come after init output sections
This commit is contained in:
parent
835f1fc03f
commit
e99818c602
@ -1282,6 +1282,9 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
|
||||
try self.finalizeMergeSections();
|
||||
try self.initOutputSections();
|
||||
try self.initMergeSections();
|
||||
if (self.linkerDefinedPtr()) |obj| {
|
||||
try obj.initStartStopSymbols(self);
|
||||
}
|
||||
self.claimUnresolved();
|
||||
|
||||
// Scan and create missing synthetic entries such as GOT indirection.
|
||||
@ -5247,6 +5250,14 @@ pub fn calcNumIRelativeRelocs(self: *Elf) usize {
|
||||
return count;
|
||||
}
|
||||
|
||||
pub fn getStartStopBasename(self: Elf, shdr: elf.Elf64_Shdr) ?[]const u8 {
|
||||
const name = self.getShString(shdr.sh_name);
|
||||
if (shdr.sh_flags & elf.SHF_ALLOC != 0 and name.len > 0) {
|
||||
if (Elf.isCIdentifier(name)) return name;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn isCIdentifier(name: []const u8) bool {
|
||||
if (name.len == 0) return false;
|
||||
const first_c = name[0];
|
||||
|
||||
@ -42,30 +42,28 @@ pub fn init(self: *LinkerDefined, allocator: Allocator) !void {
|
||||
try self.strtab.append(allocator, 0);
|
||||
}
|
||||
|
||||
pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
|
||||
const newSymbolAssumeCapacity = struct {
|
||||
fn newSymbolAssumeCapacity(ld: *LinkerDefined, name_off: u32, ef: *Elf) Symbol.Index {
|
||||
const esym_index: u32 = @intCast(ld.symtab.items.len);
|
||||
const esym = ld.symtab.addOneAssumeCapacity();
|
||||
esym.* = .{
|
||||
.st_name = name_off,
|
||||
.st_info = elf.STB_GLOBAL << 4,
|
||||
.st_other = @intFromEnum(elf.STV.HIDDEN),
|
||||
.st_shndx = elf.SHN_ABS,
|
||||
.st_value = 0,
|
||||
.st_size = 0,
|
||||
};
|
||||
const index = ld.addSymbolAssumeCapacity();
|
||||
const symbol = &ld.symbols.items[index];
|
||||
symbol.name_offset = name_off;
|
||||
symbol.extra_index = ld.addSymbolExtraAssumeCapacity(.{});
|
||||
symbol.ref = .{ .index = 0, .file = 0 };
|
||||
symbol.esym_index = esym_index;
|
||||
symbol.version_index = ef.default_sym_version;
|
||||
return index;
|
||||
}
|
||||
}.newSymbolAssumeCapacity;
|
||||
fn newSymbolAssumeCapacity(self: *LinkerDefined, name_off: u32, elf_file: *Elf) Symbol.Index {
|
||||
const esym_index: u32 = @intCast(self.symtab.items.len);
|
||||
const esym = self.symtab.addOneAssumeCapacity();
|
||||
esym.* = .{
|
||||
.st_name = name_off,
|
||||
.st_info = elf.STB_GLOBAL << 4,
|
||||
.st_other = @intFromEnum(elf.STV.HIDDEN),
|
||||
.st_shndx = elf.SHN_ABS,
|
||||
.st_value = 0,
|
||||
.st_size = 0,
|
||||
};
|
||||
const index = self.addSymbolAssumeCapacity();
|
||||
const symbol = &self.symbols.items[index];
|
||||
symbol.name_offset = name_off;
|
||||
symbol.extra_index = self.addSymbolExtraAssumeCapacity(.{});
|
||||
symbol.ref = .{ .index = 0, .file = 0 };
|
||||
symbol.esym_index = esym_index;
|
||||
symbol.version_index = elf_file.default_sym_version;
|
||||
return index;
|
||||
}
|
||||
|
||||
pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
|
||||
const gpa = elf_file.base.comp.gpa;
|
||||
|
||||
var nsyms: usize = 0;
|
||||
@ -93,18 +91,6 @@ pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
|
||||
nsyms += 1; // __global_pointer$
|
||||
}
|
||||
|
||||
var start_stop_count: usize = 0;
|
||||
for (elf_file.objects.items) |index| {
|
||||
const object = elf_file.file(index).?.object;
|
||||
for (object.shdrs.items) |shdr| {
|
||||
if (object.getStartStopBasename(shdr)) |_| {
|
||||
start_stop_count += 2; // __start_, __stop_
|
||||
}
|
||||
}
|
||||
}
|
||||
nsyms += start_stop_count;
|
||||
|
||||
try self.start_stop_indexes.ensureTotalCapacityPrecise(gpa, start_stop_count);
|
||||
try self.symtab.ensureTotalCapacityPrecise(gpa, nsyms);
|
||||
try self.symbols.ensureTotalCapacityPrecise(gpa, nsyms);
|
||||
try self.symbols_extra.ensureTotalCapacityPrecise(gpa, nsyms * @sizeOf(Symbol.Extra));
|
||||
@ -113,44 +99,67 @@ pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
|
||||
@memset(self.symbols_resolver.items, 0);
|
||||
|
||||
if (elf_file.entry_name) |name| {
|
||||
self.entry_index = newSymbolAssumeCapacity(self, try self.addString(gpa, name), elf_file);
|
||||
self.entry_index = self.newSymbolAssumeCapacity(try self.addString(gpa, name), elf_file);
|
||||
}
|
||||
|
||||
self.dynamic_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_DYNAMIC"), elf_file);
|
||||
self.ehdr_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__ehdr_start"), elf_file);
|
||||
self.init_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__init_array_start"), elf_file);
|
||||
self.init_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__init_array_end"), elf_file);
|
||||
self.fini_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__fini_array_start"), elf_file);
|
||||
self.fini_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__fini_array_end"), elf_file);
|
||||
self.preinit_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__preinit_array_start"), elf_file);
|
||||
self.preinit_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__preinit_array_end"), elf_file);
|
||||
self.got_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_GLOBAL_OFFSET_TABLE_"), elf_file);
|
||||
self.plt_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_PROCEDURE_LINKAGE_TABLE_"), elf_file);
|
||||
self.end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_end"), elf_file);
|
||||
self.dynamic_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "_DYNAMIC"), elf_file);
|
||||
self.ehdr_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__ehdr_start"), elf_file);
|
||||
self.init_array_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__init_array_start"), elf_file);
|
||||
self.init_array_end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__init_array_end"), elf_file);
|
||||
self.fini_array_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__fini_array_start"), elf_file);
|
||||
self.fini_array_end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__fini_array_end"), elf_file);
|
||||
self.preinit_array_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__preinit_array_start"), elf_file);
|
||||
self.preinit_array_end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__preinit_array_end"), elf_file);
|
||||
self.got_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "_GLOBAL_OFFSET_TABLE_"), elf_file);
|
||||
self.plt_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "_PROCEDURE_LINKAGE_TABLE_"), elf_file);
|
||||
self.end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "_end"), elf_file);
|
||||
|
||||
if (elf_file.base.comp.link_eh_frame_hdr) {
|
||||
self.gnu_eh_frame_hdr_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__GNU_EH_FRAME_HDR"), elf_file);
|
||||
self.gnu_eh_frame_hdr_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__GNU_EH_FRAME_HDR"), elf_file);
|
||||
}
|
||||
|
||||
self.dso_handle_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__dso_handle"), elf_file);
|
||||
self.rela_iplt_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__rela_iplt_start"), elf_file);
|
||||
self.rela_iplt_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__rela_iplt_end"), elf_file);
|
||||
self.dso_handle_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__dso_handle"), elf_file);
|
||||
self.rela_iplt_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__rela_iplt_start"), elf_file);
|
||||
self.rela_iplt_end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__rela_iplt_end"), elf_file);
|
||||
|
||||
if (elf_file.getTarget().cpu.arch.isRISCV() and elf_file.isEffectivelyDynLib()) {
|
||||
self.global_pointer_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__global_pointer$"), elf_file);
|
||||
self.global_pointer_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__global_pointer$"), elf_file);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn initStartStopSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
|
||||
const gpa = elf_file.base.comp.gpa;
|
||||
|
||||
var nsyms: usize = 0;
|
||||
for (elf_file.shdrs.items) |shdr| {
|
||||
if (elf_file.getStartStopBasename(shdr)) |_| {
|
||||
nsyms += 2; // __start_, __stop_
|
||||
}
|
||||
}
|
||||
|
||||
for (elf_file.objects.items) |index| {
|
||||
const object = elf_file.file(index).?.object;
|
||||
for (object.shdrs.items) |shdr| {
|
||||
if (object.getStartStopBasename(shdr)) |name| {
|
||||
const start_name = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name});
|
||||
defer gpa.free(start_name);
|
||||
const stop_name = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name});
|
||||
defer gpa.free(stop_name);
|
||||
const start = newSymbolAssumeCapacity(self, try self.addString(gpa, start_name), elf_file);
|
||||
const stop = newSymbolAssumeCapacity(self, try self.addString(gpa, stop_name), elf_file);
|
||||
self.start_stop_indexes.appendSliceAssumeCapacity(&.{ start, stop });
|
||||
try self.start_stop_indexes.ensureTotalCapacityPrecise(gpa, nsyms);
|
||||
try self.symtab.ensureUnusedCapacity(gpa, nsyms);
|
||||
try self.symbols.ensureUnusedCapacity(gpa, nsyms);
|
||||
try self.symbols_extra.ensureUnusedCapacity(gpa, nsyms * @sizeOf(Symbol.Extra));
|
||||
try self.symbols_resolver.ensureUnusedCapacity(gpa, nsyms);
|
||||
|
||||
for (elf_file.shdrs.items) |shdr| {
|
||||
if (elf_file.getStartStopBasename(shdr)) |name| {
|
||||
const start_name = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name});
|
||||
defer gpa.free(start_name);
|
||||
const stop_name = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name});
|
||||
defer gpa.free(stop_name);
|
||||
|
||||
for (&[_][]const u8{ start_name, stop_name }) |nn| {
|
||||
const index = self.newSymbolAssumeCapacity(try self.addString(gpa, nn), elf_file);
|
||||
self.start_stop_indexes.appendAssumeCapacity(index);
|
||||
const gop = try elf_file.resolver.getOrPut(gpa, .{
|
||||
.index = index,
|
||||
.file = self.index,
|
||||
}, elf_file);
|
||||
assert(!gop.found_existing);
|
||||
gop.ref.* = .{ .index = index, .file = self.index };
|
||||
self.symbols_resolver.appendAssumeCapacity(gop.index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1399,14 +1399,6 @@ pub fn comdatGroup(self: *Object, index: Elf.ComdatGroup.Index) *Elf.ComdatGroup
|
||||
return &self.comdat_groups.items[index];
|
||||
}
|
||||
|
||||
pub fn getStartStopBasename(self: Object, shdr: elf.Elf64_Shdr) ?[]const u8 {
|
||||
const name = self.getString(shdr.sh_name);
|
||||
if (shdr.sh_flags & elf.SHF_ALLOC != 0 and name.len > 0) {
|
||||
if (Elf.isCIdentifier(name)) return name;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn format(
|
||||
self: *Object,
|
||||
comptime unused_fmt_string: []const u8,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user