unify parsing codepaths between relocatable and non

This commit is contained in:
Andrew Kelley
2024-10-18 23:32:10 -07:00
parent 12f3a7c3c2
commit de0f7fcf52
3 changed files with 21 additions and 60 deletions

View File

@@ -765,6 +765,7 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {
const target = self.getTarget();
const debug_fmt_strip = comp.config.debug_format == .strip;
const default_sym_version = self.default_sym_version;
const is_static_lib = self.base.isStaticLib();
if (comp.verbose_link) {
const argv = &self.dump_argv_list;
@@ -780,7 +781,7 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {
.res => unreachable,
.dso_exact => @panic("TODO"),
.object => |obj| try parseObject(self, obj),
.archive => |obj| try parseArchive(gpa, diags, &self.file_handles, &self.files, &self.first_eflags, target, debug_fmt_strip, default_sym_version, &self.objects, obj),
.archive => |obj| try parseArchive(gpa, diags, &self.file_handles, &self.files, &self.first_eflags, target, debug_fmt_strip, default_sym_version, &self.objects, obj, is_static_lib),
.dso => |dso| try parseDso(gpa, diags, dso, &self.shared_objects, &self.files, target),
}
}
@@ -823,17 +824,17 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
if (self.zigObjectPtr()) |zig_object| try zig_object.flush(self, tid);
if (module_obj_path) |path| openParseObjectReportingFailure(self, path);
switch (comp.config.output_mode) {
.Obj => return relocatable.flushObject(self, comp, module_obj_path),
.Obj => return relocatable.flushObject(self, comp),
.Lib => switch (comp.config.link_mode) {
.dynamic => {},
.static => return relocatable.flushStaticLib(self, comp, module_obj_path),
.static => return relocatable.flushStaticLib(self, comp),
},
.Exe => {},
}
if (module_obj_path) |path| openParseObjectReportingFailure(self, path);
if (diags.hasErrors()) return error.FlushFailure;
// If we haven't already, create a linker-generated input file comprising of
@@ -1149,7 +1150,10 @@ fn parseObject(self: *Elf, obj: link.Input.Object) ParseError!void {
try self.objects.append(gpa, index);
const object = self.file(index).?.object;
try object.parse(gpa, diags, obj.path, handle, first_eflags, target, debug_fmt_strip, default_sym_version);
try object.parseCommon(gpa, diags, obj.path, handle, target, first_eflags);
if (!self.base.isStaticLib()) {
try object.parse(gpa, diags, obj.path, handle, target, debug_fmt_strip, default_sym_version);
}
}
fn parseArchive(
@@ -1163,6 +1167,7 @@ fn parseArchive(
default_sym_version: elf.Versym,
objects: *std.ArrayListUnmanaged(File.Index),
obj: link.Input.Object,
is_static_lib: bool,
) ParseError!void {
const tracy = trace(@src());
defer tracy.end();
@@ -1171,13 +1176,17 @@ fn parseArchive(
var archive = try Archive.parse(gpa, diags, file_handles, obj.path, fh);
defer archive.deinit(gpa);
const init_alive = if (is_static_lib) true else obj.must_link;
for (archive.objects) |extracted| {
const index: File.Index = @intCast(try files.addOne(gpa));
files.set(index, .{ .object = extracted });
const object = &files.items(.data)[index].object;
object.index = index;
object.alive = obj.must_link;
try object.parse(gpa, diags, obj.path, obj.file, first_eflags, target, debug_fmt_strip, default_sym_version);
object.alive = init_alive;
try object.parseCommon(gpa, diags, obj.path, obj.file, target, first_eflags);
if (!is_static_lib)
try object.parse(gpa, diags, obj.path, obj.file, target, debug_fmt_strip, default_sym_version);
try objects.append(gpa, index);
}
}

View File

@@ -69,13 +69,10 @@ pub fn parse(
/// For error reporting purposes only.
path: Path,
handle: fs.File,
first_eflags: *?elf.Word,
target: std.Target,
debug_fmt_strip: bool,
default_sym_version: elf.Versym,
) !void {
try self.parseCommon(gpa, diags, path, handle, first_eflags, target);
// Append null input merge section
try self.input_merge_sections.append(gpa, .{});
// Allocate atom index 0 to null atom
@@ -95,14 +92,14 @@ pub fn parse(
}
}
fn parseCommon(
pub fn parseCommon(
self: *Object,
gpa: Allocator,
diags: *Diags,
path: Path,
handle: fs.File,
first_eflags: *?elf.Word,
target: std.Target,
first_eflags: *?elf.Word,
) !void {
const offset = if (self.archive) |ar| ar.offset else 0;
const file_size = (try handle.stat()).size;
@@ -1036,15 +1033,6 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void {
}
}
pub fn parseAr(self: *Object, path: Path, elf_file: *Elf) !void {
const gpa = elf_file.base.comp.gpa;
const diags = &elf_file.base.comp.link_diags;
const handle = elf_file.fileHandle(self.file_handle);
const first_eflags = &elf_file.first_eflags;
const target = elf_file.base.comp.root_mod.resolved_target.result;
try self.parseCommon(gpa, diags, path, handle, first_eflags, target);
}
pub fn updateArSymtab(self: Object, ar_symtab: *Archive.ArSymtab, elf_file: *Elf) !void {
const comp = elf_file.base.comp;
const gpa = comp.gpa;

View File

@@ -1,11 +1,7 @@
pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?Path) link.File.FlushError!void {
pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) link.File.FlushError!void {
const gpa = comp.gpa;
const diags = &comp.link_diags;
if (module_obj_path) |path| {
parseObjectStaticLibReportingFailure(elf_file, path);
}
if (diags.hasErrors()) return error.FlushFailure;
// First, we flush relocatable object file generated with our backends.
@@ -134,11 +130,9 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?Path
if (diags.hasErrors()) return error.FlushFailure;
}
pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?Path) link.File.FlushError!void {
pub fn flushObject(elf_file: *Elf, comp: *Compilation) link.File.FlushError!void {
const diags = &comp.link_diags;
if (module_obj_path) |path| elf_file.openParseObjectReportingFailure(path);
if (diags.hasErrors()) return error.FlushFailure;
// Now, we are ready to resolve the symbols across all input files.
@@ -188,36 +182,6 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?Path) l
if (diags.hasErrors()) return error.FlushFailure;
}
fn parseObjectStaticLibReportingFailure(elf_file: *Elf, path: Path) void {
const diags = &elf_file.base.comp.link_diags;
parseObjectStaticLib(elf_file, path) catch |err| switch (err) {
error.LinkFailure => return,
else => |e| diags.addParseError(path, "parsing object failed: {s}", .{@errorName(e)}),
};
}
fn parseObjectStaticLib(elf_file: *Elf, path: Path) Elf.ParseError!void {
const gpa = elf_file.base.comp.gpa;
const file_handles = &elf_file.file_handles;
const handle = try path.root_dir.handle.openFile(path.sub_path, .{});
const fh = try Elf.addFileHandle(gpa, file_handles, handle);
const index: File.Index = @intCast(try elf_file.files.addOne(gpa));
elf_file.files.set(index, .{ .object = .{
.path = .{
.root_dir = path.root_dir,
.sub_path = try gpa.dupe(u8, path.sub_path),
},
.file_handle = fh,
.index = index,
} });
try elf_file.objects.append(gpa, index);
const object = elf_file.file(index).?.object;
try object.parseAr(path, elf_file);
}
fn claimUnresolved(elf_file: *Elf) void {
if (elf_file.zigObjectPtr()) |zig_object| {
zig_object.claimUnresolvedRelocatable(elf_file);