mirror of
https://github.com/ziglang/zig.git
synced 2026-01-09 17:05:16 +00:00
elf: fix synthetic section handling and actually parse DSOs
This commit is contained in:
parent
d1446565a1
commit
5fa90afb64
@ -1678,6 +1678,8 @@ fn parseLibrary(
|
||||
|
||||
if (Archive.isArchive(in_file)) {
|
||||
try self.parseArchive(in_file, lib.path, must_link, ctx);
|
||||
} else if (SharedObject.isSharedObject(in_file)) {
|
||||
try self.parseSharedObject(in_file, lib, ctx);
|
||||
} else return error.UnknownFileType;
|
||||
}
|
||||
|
||||
@ -1732,6 +1734,34 @@ fn parseArchive(
|
||||
}
|
||||
}
|
||||
|
||||
fn parseSharedObject(
|
||||
self: *Elf,
|
||||
in_file: std.fs.File,
|
||||
lib: SystemLib,
|
||||
ctx: *ParseErrorCtx,
|
||||
) ParseError!void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const gpa = self.base.allocator;
|
||||
const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32));
|
||||
const index = @as(File.Index, @intCast(try self.files.addOne(gpa)));
|
||||
self.files.set(index, .{ .shared_object = .{
|
||||
.path = lib.path,
|
||||
.data = data,
|
||||
.index = index,
|
||||
.needed = lib.needed,
|
||||
.alive = lib.needed,
|
||||
} });
|
||||
try self.shared_objects.append(gpa, index);
|
||||
|
||||
const shared_object = self.file(index).?.shared_object;
|
||||
try shared_object.parse(self);
|
||||
|
||||
ctx.detected_cpu_arch = shared_object.header.?.e_machine.toTargetCpuArch().?;
|
||||
if (ctx.detected_cpu_arch != self.base.options.target.cpu.arch) return error.InvalidCpuArch;
|
||||
}
|
||||
|
||||
/// When resolving symbols, we approach the problem similarly to `mold`.
|
||||
/// 1. Resolve symbols across all objects (including those preemptively extracted archives).
|
||||
/// 2. Resolve symbols across all shared objects.
|
||||
@ -3437,23 +3467,23 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {
|
||||
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);
|
||||
for (self.objects.items) |index| {
|
||||
const object = self.file(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);
|
||||
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));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
self.start_stop_indexes.appendAssumeCapacity(try linker_defined.addGlobal(start, self));
|
||||
self.start_stop_indexes.appendAssumeCapacity(try linker_defined.addGlobal(stop, self));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
linker_defined.resolveSymbols(self);
|
||||
}
|
||||
@ -5199,6 +5229,15 @@ pub fn isCIdentifier(name: []const u8) bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
fn getStartStopBasename(self: *Elf, atom_index: Atom.Index) ?[]const u8 {
|
||||
const atom_ptr = self.atom(atom_index) orelse return null;
|
||||
const name = atom_ptr.name(self);
|
||||
if (atom_ptr.inputShdr(self).sh_flags & elf.SHF_ALLOC != 0 and name.len > 0) {
|
||||
if (isCIdentifier(name)) return name;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn atom(self: *Elf, atom_index: Atom.Index) ?*Atom {
|
||||
if (atom_index == 0) return null;
|
||||
assert(atom_index < self.atoms.items.len);
|
||||
|
||||
@ -970,7 +970,7 @@ pub const ElfShdr = struct {
|
||||
sh_addralign: u64,
|
||||
sh_entsize: u64,
|
||||
|
||||
fn fromElf64Shdr(shdr: elf.Elf64_Shdr) error{Overflow}!ElfShdr {
|
||||
pub fn fromElf64Shdr(shdr: elf.Elf64_Shdr) error{Overflow}!ElfShdr {
|
||||
return .{
|
||||
.sh_name = shdr.sh_name,
|
||||
.sh_type = shdr.sh_type,
|
||||
|
||||
@ -33,6 +33,7 @@ pub fn isSharedObject(file: std.fs.File) bool {
|
||||
}
|
||||
|
||||
pub fn deinit(self: *SharedObject, allocator: Allocator) void {
|
||||
allocator.free(self.data);
|
||||
self.versyms.deinit(allocator);
|
||||
self.verstrings.deinit(allocator);
|
||||
self.symbols.deinit(allocator);
|
||||
@ -139,7 +140,7 @@ fn initSymtab(self: *SharedObject, elf_file: *Elf) !void {
|
||||
defer gpa.free(full_name);
|
||||
break :blk try elf_file.strtab.insert(gpa, full_name);
|
||||
} else try elf_file.strtab.insert(gpa, name);
|
||||
const gop = try elf_file.getOrCreateGlobal(off);
|
||||
const gop = try elf_file.getOrPutGlobal(off);
|
||||
self.symbols.addOneAssumeCapacity().* = gop.index;
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,8 +284,12 @@ pub const GotSection = struct {
|
||||
entry.tag = .got;
|
||||
entry.symbol_index = sym_index;
|
||||
const symbol = elf_file.symbol(sym_index);
|
||||
if (symbol.flags.import or symbol.isIFunc(elf_file) or (elf_file.base.options.pic and !symbol.isAbs(elf_file)))
|
||||
symbol.flags.has_got = true;
|
||||
if (symbol.flags.import or symbol.isIFunc(elf_file) or
|
||||
(elf_file.base.options.pic and !symbol.isAbs(elf_file)))
|
||||
{
|
||||
got.flags.needs_rela = true;
|
||||
}
|
||||
if (symbol.extra(elf_file)) |extra| {
|
||||
var new_extra = extra;
|
||||
new_extra.got = index;
|
||||
@ -310,6 +314,7 @@ pub const GotSection = struct {
|
||||
entry.tag = .tlsgd;
|
||||
entry.symbol_index = sym_index;
|
||||
const symbol = elf_file.symbol(sym_index);
|
||||
symbol.flags.has_tlsgd = true;
|
||||
if (symbol.flags.import or elf_file.isDynLib()) got.flags.needs_rela = true;
|
||||
if (symbol.extra(elf_file)) |extra| {
|
||||
var new_extra = extra;
|
||||
@ -324,6 +329,7 @@ pub const GotSection = struct {
|
||||
entry.tag = .gottp;
|
||||
entry.symbol_index = sym_index;
|
||||
const symbol = elf_file.symbol(sym_index);
|
||||
symbol.flags.has_gottp = true;
|
||||
if (symbol.flags.import or elf_file.isDynLib()) got.flags.needs_rela = true;
|
||||
if (symbol.extra(elf_file)) |extra| {
|
||||
var new_extra = extra;
|
||||
@ -338,6 +344,7 @@ pub const GotSection = struct {
|
||||
entry.tag = .tlsdesc;
|
||||
entry.symbol_index = sym_index;
|
||||
const symbol = elf_file.symbol(sym_index);
|
||||
symbol.flags.has_tlsdesc = true;
|
||||
got.flags.needs_rela = true;
|
||||
if (symbol.extra(elf_file)) |extra| {
|
||||
var new_extra = extra;
|
||||
@ -645,6 +652,7 @@ pub const PltSection = struct {
|
||||
pub fn addSymbol(plt: *PltSection, sym_index: Symbol.Index, elf_file: *Elf) !void {
|
||||
const index = @as(u32, @intCast(plt.symbols.items.len));
|
||||
const symbol = elf_file.symbol(sym_index);
|
||||
symbol.flags.has_plt = true;
|
||||
if (symbol.extra(elf_file)) |extra| {
|
||||
var new_extra = extra;
|
||||
new_extra.plt = index;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user