authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-10-16 18:48:43-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-10-23 16:27:38-07:00
log2dcfa723767d284cef5eb180be7c080583ddbe25
tree43056d154bda710c6478f5a13688e712e636b633
parentb510c5719f3cfd55ee70da5a1005396d28dd1c1d

link.Elf: untangle parseObject and parseArchive

from link.Elf, so that they can be used earlier in the pipeline

7 files changed, 363 insertions(+), 289 deletions(-)

src/link/Elf.zig+46-67
...@@ -1398,8 +1398,15 @@ fn parseObject(self: *Elf, obj: link.Input.Object) ParseError!void {...@@ -1398,8 +1398,15 @@ fn parseObject(self: *Elf, obj: link.Input.Object) ParseError!void {
1398 defer tracy.end();1398 defer tracy.end();
13991399
1400 const gpa = self.base.comp.gpa;1400 const gpa = self.base.comp.gpa;
1401 const diags = &self.base.comp.link_diags;
1402 const first_eflags = &self.first_eflags;
1403 const target = self.base.comp.root_mod.resolved_target.result;
1404 const debug_fmt_strip = self.base.comp.config.debug_format == .strip;
1405 const default_sym_version = self.default_sym_version;
1406 const file_handles = &self.file_handles;
1407
1401 const handle = obj.file;1408 const handle = obj.file;
1402 const fh = try self.addFileHandle(handle);1409 const fh = try addFileHandle(gpa, file_handles, handle);
14031410
1404 const index: File.Index = @intCast(try self.files.addOne(gpa));1411 const index: File.Index = @intCast(try self.files.addOne(gpa));
1405 self.files.set(index, .{ .object = .{1412 self.files.set(index, .{ .object = .{
...@@ -1413,7 +1420,7 @@ fn parseObject(self: *Elf, obj: link.Input.Object) ParseError!void {...@@ -1413,7 +1420,7 @@ fn parseObject(self: *Elf, obj: link.Input.Object) ParseError!void {
1413 try self.objects.append(gpa, index);1420 try self.objects.append(gpa, index);
14141421
1415 const object = self.file(index).?.object;1422 const object = self.file(index).?.object;
1416 try object.parse(self);1423 try object.parse(gpa, diags, obj.path, handle, first_eflags, target, debug_fmt_strip, default_sym_version);
1417}1424}
14181425
1419pub fn openParseArchiveReportingFailure(self: *Elf, path: Path) void {1426pub fn openParseArchiveReportingFailure(self: *Elf, path: Path) void {
...@@ -1427,36 +1434,49 @@ pub fn openParseArchiveReportingFailure(self: *Elf, path: Path) void {...@@ -1427,36 +1434,49 @@ pub fn openParseArchiveReportingFailure(self: *Elf, path: Path) void {
1427}1434}
14281435
1429pub fn parseArchiveReportingFailure(self: *Elf, obj: link.Input.Object) void {1436pub fn parseArchiveReportingFailure(self: *Elf, obj: link.Input.Object) void {
1437 const gpa = self.base.comp.gpa;
1430 const diags = &self.base.comp.link_diags;1438 const diags = &self.base.comp.link_diags;
1431 self.parseArchive(obj) catch |err| switch (err) {1439 const first_eflags = &self.first_eflags;
1440 const target = self.base.comp.root_mod.resolved_target.result;
1441 const debug_fmt_strip = self.base.comp.config.debug_format == .strip;
1442 const default_sym_version = self.default_sym_version;
1443 const file_handles = &self.file_handles;
1444 const files = &self.files;
1445 const objects = &self.objects;
1446
1447 parseArchive(gpa, diags, file_handles, files, first_eflags, target, debug_fmt_strip, default_sym_version, objects, obj) catch |err| switch (err) {
1432 error.LinkFailure => return, // already reported1448 error.LinkFailure => return, // already reported
1433 else => |e| diags.addParseError(obj.path, "failed to parse archive: {s}", .{@errorName(e)}),1449 else => |e| diags.addParseError(obj.path, "failed to parse archive: {s}", .{@errorName(e)}),
1434 };1450 };
1435}1451}
14361452
1437fn parseArchive(self: *Elf, obj: link.Input.Object) ParseError!void {1453fn parseArchive(
1454 gpa: Allocator,
1455 diags: *Diags,
1456 file_handles: *std.ArrayListUnmanaged(File.Handle),
1457 files: *std.MultiArrayList(File.Entry),
1458 first_eflags: *?elf.Word,
1459 target: std.Target,
1460 debug_fmt_strip: bool,
1461 default_sym_version: elf.Versym,
1462 objects: *std.ArrayListUnmanaged(File.Index),
1463 obj: link.Input.Object,
1464) ParseError!void {
1438 const tracy = trace(@src());1465 const tracy = trace(@src());
1439 defer tracy.end();1466 defer tracy.end();
14401467
1441 const gpa = self.base.comp.gpa;1468 const fh = try addFileHandle(gpa, file_handles, obj.file);
1442 const handle = obj.file;1469 var archive = try Archive.parse(gpa, diags, file_handles, obj.path, fh);
1443 const fh = try self.addFileHandle(handle);
1444
1445 var archive: Archive = .{};
1446 defer archive.deinit(gpa);1470 defer archive.deinit(gpa);
1447 try archive.parse(self, obj.path, fh);
1448
1449 const objects = try archive.objects.toOwnedSlice(gpa);
1450 defer gpa.free(objects);
14511471
1452 for (objects) |extracted| {1472 for (archive.objects) |extracted| {
1453 const index: File.Index = @intCast(try self.files.addOne(gpa));1473 const index: File.Index = @intCast(try files.addOne(gpa));
1454 self.files.set(index, .{ .object = extracted });1474 files.set(index, .{ .object = extracted });
1455 const object = &self.files.items(.data)[index].object;1475 const object = &files.items(.data)[index].object;
1456 object.index = index;1476 object.index = index;
1457 object.alive = obj.must_link;1477 object.alive = obj.must_link;
1458 try object.parse(self);1478 try object.parse(gpa, diags, obj.path, obj.file, first_eflags, target, debug_fmt_strip, default_sym_version);
1459 try self.objects.append(gpa, index);1479 try objects.append(gpa, index);
1460 }1480 }
1461}1481}
14621482
...@@ -1565,46 +1585,6 @@ fn parseDso(...@@ -1565,46 +1585,6 @@ fn parseDso(
1565 }1585 }
1566}1586}
15671587
1568pub fn validateEFlags(self: *Elf, file_index: File.Index, e_flags: elf.Word) !void {
1569 if (self.first_eflags == null) {
1570 self.first_eflags = e_flags;
1571 return; // there isn't anything to conflict with yet
1572 }
1573 const self_eflags: *elf.Word = &self.first_eflags.?;
1574
1575 switch (self.getTarget().cpu.arch) {
1576 .riscv64 => {
1577 if (e_flags != self_eflags.*) {
1578 const riscv_eflags: riscv.RiscvEflags = @bitCast(e_flags);
1579 const self_riscv_eflags: *riscv.RiscvEflags = @ptrCast(self_eflags);
1580
1581 self_riscv_eflags.rvc = self_riscv_eflags.rvc or riscv_eflags.rvc;
1582 self_riscv_eflags.tso = self_riscv_eflags.tso or riscv_eflags.tso;
1583
1584 var any_errors: bool = false;
1585 if (self_riscv_eflags.fabi != riscv_eflags.fabi) {
1586 any_errors = true;
1587 try self.addFileError(
1588 file_index,
1589 "cannot link object files with different float-point ABIs",
1590 .{},
1591 );
1592 }
1593 if (self_riscv_eflags.rve != riscv_eflags.rve) {
1594 any_errors = true;
1595 try self.addFileError(
1596 file_index,
1597 "cannot link object files with different RVEs",
1598 .{},
1599 );
1600 }
1601 if (any_errors) return error.LinkFailure;
1602 }
1603 },
1604 else => {},
1605 }
1606}
1607
1608/// When resolving symbols, we approach the problem similarly to `mold`.1588/// When resolving symbols, we approach the problem similarly to `mold`.
1609/// 1. Resolve symbols across all objects (including those preemptively extracted archives).1589/// 1. Resolve symbols across all objects (including those preemptively extracted archives).
1610/// 2. Resolve symbols across all shared objects.1590/// 2. Resolve symbols across all shared objects.
...@@ -4704,16 +4684,16 @@ fn fileLookup(files: std.MultiArrayList(File.Entry), index: File.Index) ?File {...@@ -4704,16 +4684,16 @@ fn fileLookup(files: std.MultiArrayList(File.Entry), index: File.Index) ?File {
4704 };4684 };
4705}4685}
47064686
4707pub fn addFileHandle(self: *Elf, handle: fs.File) !File.HandleIndex {4687pub fn addFileHandle(
4708 const gpa = self.base.comp.gpa;4688 gpa: Allocator,
4709 const index: File.HandleIndex = @intCast(self.file_handles.items.len);4689 file_handles: *std.ArrayListUnmanaged(File.Handle),
4710 const fh = try self.file_handles.addOne(gpa);4690 handle: fs.File,
4711 fh.* = handle;4691) Allocator.Error!File.HandleIndex {
4712 return index;4692 try file_handles.append(gpa, handle);
4693 return @intCast(file_handles.items.len - 1);
4713}4694}
47144695
4715pub fn fileHandle(self: Elf, index: File.HandleIndex) File.Handle {4696pub fn fileHandle(self: Elf, index: File.HandleIndex) File.Handle {
4716 assert(index < self.file_handles.items.len);
4717 return self.file_handles.items[index];4697 return self.file_handles.items[index];
4718}4698}
47194699
...@@ -5588,4 +5568,3 @@ const Thunk = @import("Elf/Thunk.zig");...@@ -5588,4 +5568,3 @@ const Thunk = @import("Elf/Thunk.zig");
5588const Value = @import("../Value.zig");5568const Value = @import("../Value.zig");
5589const VerneedSection = synthetic_sections.VerneedSection;5569const VerneedSection = synthetic_sections.VerneedSection;
5590const ZigObject = @import("Elf/ZigObject.zig");5570const ZigObject = @import("Elf/ZigObject.zig");
5591const riscv = @import("riscv.zig");
src/link/Elf/Archive.zig+36-20
...@@ -1,18 +1,29 @@...@@ -1,18 +1,29 @@
1objects: std.ArrayListUnmanaged(Object) = .empty,1objects: []const Object,
2strtab: std.ArrayListUnmanaged(u8) = .empty,2/// '\n'-delimited
33strtab: []const u8,
4pub fn deinit(self: *Archive, allocator: Allocator) void {4
5 self.objects.deinit(allocator);5pub fn deinit(a: *Archive, gpa: Allocator) void {
6 self.strtab.deinit(allocator);6 gpa.free(a.objects);
7 gpa.free(a.strtab);
8 a.* = undefined;
7}9}
810
9pub fn parse(self: *Archive, elf_file: *Elf, path: Path, handle_index: File.HandleIndex) !void {11pub fn parse(
10 const comp = elf_file.base.comp;12 gpa: Allocator,
11 const gpa = comp.gpa;13 diags: *Diags,
12 const diags = &comp.link_diags;14 file_handles: *const std.ArrayListUnmanaged(File.Handle),
13 const handle = elf_file.fileHandle(handle_index);15 path: Path,
16 handle_index: File.HandleIndex,
17) !Archive {
18 const handle = file_handles.items[handle_index];
14 const size = (try handle.stat()).size;19 const size = (try handle.stat()).size;
1520
21 var objects: std.ArrayListUnmanaged(Object) = .empty;
22 defer objects.deinit(gpa);
23
24 var strtab: std.ArrayListUnmanaged(u8) = .empty;
25 defer strtab.deinit(gpa);
26
16 var pos: usize = elf.ARMAG.len;27 var pos: usize = elf.ARMAG.len;
17 while (true) {28 while (true) {
18 if (pos >= size) break;29 if (pos >= size) break;
...@@ -37,8 +48,8 @@ pub fn parse(self: *Archive, elf_file: *Elf, path: Path, handle_index: File.Hand...@@ -37,8 +48,8 @@ pub fn parse(self: *Archive, elf_file: *Elf, path: Path, handle_index: File.Hand
3748
38 if (hdr.isSymtab() or hdr.isSymtab64()) continue;49 if (hdr.isSymtab() or hdr.isSymtab64()) continue;
39 if (hdr.isStrtab()) {50 if (hdr.isStrtab()) {
40 try self.strtab.resize(gpa, obj_size);51 try strtab.resize(gpa, obj_size);
41 const amt = try handle.preadAll(self.strtab.items, pos);52 const amt = try handle.preadAll(strtab.items, pos);
42 if (amt != obj_size) return error.InputOutput;53 if (amt != obj_size) return error.InputOutput;
43 continue;54 continue;
44 }55 }
...@@ -47,7 +58,7 @@ pub fn parse(self: *Archive, elf_file: *Elf, path: Path, handle_index: File.Hand...@@ -47,7 +58,7 @@ pub fn parse(self: *Archive, elf_file: *Elf, path: Path, handle_index: File.Hand
47 const name = if (hdr.name()) |name|58 const name = if (hdr.name()) |name|
48 name59 name
49 else if (try hdr.nameOffset()) |off|60 else if (try hdr.nameOffset()) |off|
50 self.getString(off)61 stringTableLookup(strtab.items, off)
51 else62 else
52 unreachable;63 unreachable;
5364
...@@ -70,14 +81,18 @@ pub fn parse(self: *Archive, elf_file: *Elf, path: Path, handle_index: File.Hand...@@ -70,14 +81,18 @@ pub fn parse(self: *Archive, elf_file: *Elf, path: Path, handle_index: File.Hand
70 @as(Path, object.path), @as(Path, path),81 @as(Path, object.path), @as(Path, path),
71 });82 });
7283
73 try self.objects.append(gpa, object);84 try objects.append(gpa, object);
74 }85 }
86
87 return .{
88 .objects = try objects.toOwnedSlice(gpa),
89 .strtab = try strtab.toOwnedSlice(gpa),
90 };
75}91}
7692
77fn getString(self: Archive, off: u32) []const u8 {93pub fn stringTableLookup(strtab: []const u8, off: u32) [:'\n']const u8 {
78 assert(off < self.strtab.items.len);94 const slice = strtab[off..];
79 const name = mem.sliceTo(@as([*:'\n']const u8, @ptrCast(self.strtab.items.ptr + off)), 0);95 return slice[0..mem.indexOfScalar(u8, slice, '\n').? :'\n'];
80 return name[0 .. name.len - 1];
81}96}
8297
83pub fn setArHdr(opts: struct {98pub fn setArHdr(opts: struct {
...@@ -290,8 +305,9 @@ const fs = std.fs;...@@ -290,8 +305,9 @@ const fs = std.fs;
290const log = std.log.scoped(.link);305const log = std.log.scoped(.link);
291const mem = std.mem;306const mem = std.mem;
292const Path = std.Build.Cache.Path;307const Path = std.Build.Cache.Path;
308const Allocator = std.mem.Allocator;
293309
294const Allocator = mem.Allocator;310const Diags = @import("../../link.zig").Diags;
295const Archive = @This();311const Archive = @This();
296const Elf = @import("../Elf.zig");312const Elf = @import("../Elf.zig");
297const File = @import("file.zig").File;313const File = @import("file.zig").File;
src/link/Elf/Atom.zig+27-24
...@@ -102,9 +102,13 @@ pub fn relocsShndx(self: Atom) ?u32 {...@@ -102,9 +102,13 @@ pub fn relocsShndx(self: Atom) ?u32 {
102 return self.relocs_section_index;102 return self.relocs_section_index;
103}103}
104104
105pub fn priority(self: Atom, elf_file: *Elf) u64 {105pub fn priority(atom: Atom, elf_file: *Elf) u64 {
106 const index = self.file(elf_file).?.index();106 const index = atom.file(elf_file).?.index();
107 return (@as(u64, @intCast(index)) << 32) | @as(u64, @intCast(self.input_section_index));107 return priorityLookup(index, atom.input_section_index);
108}
109
110pub fn priorityLookup(file_index: File.Index, input_section_index: u32) u64 {
111 return (@as(u64, @intCast(file_index)) << 32) | @as(u64, @intCast(input_section_index));
108}112}
109113
110/// Returns how much room there is to grow in virtual address space.114/// Returns how much room there is to grow in virtual address space.
...@@ -255,19 +259,13 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El...@@ -255,19 +259,13 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El
255 }259 }
256}260}
257261
258pub fn fdes(self: Atom, elf_file: *Elf) []Fde {262pub fn fdes(atom: Atom, object: *Object) []Fde {
259 const extras = self.extra(elf_file);263 const extras = object.atomExtra(atom.extra_index);
260 return switch (self.file(elf_file).?) {264 return object.fdes.items[extras.fde_start..][0..extras.fde_count];
261 .shared_object => unreachable,
262 .linker_defined, .zig_object => &[0]Fde{},
263 .object => |x| x.fdes.items[extras.fde_start..][0..extras.fde_count],
264 };
265}265}
266266
267pub fn markFdesDead(self: Atom, elf_file: *Elf) void {267pub fn markFdesDead(self: Atom, object: *Object) void {
268 for (self.fdes(elf_file)) |*fde| {268 for (self.fdes(object)) |*fde| fde.alive = false;
269 fde.alive = false;
270 }
271}269}
272270
273pub fn addReloc(self: Atom, alloc: Allocator, reloc: elf.Elf64_Rela, zo: *ZigObject) !void {271pub fn addReloc(self: Atom, alloc: Allocator, reloc: elf.Elf64_Rela, zo: *ZigObject) !void {
...@@ -946,16 +944,21 @@ fn format2(...@@ -946,16 +944,21 @@ fn format2(
946 atom.output_section_index, atom.alignment.toByteUnits() orelse 0, atom.size,944 atom.output_section_index, atom.alignment.toByteUnits() orelse 0, atom.size,
947 atom.prev_atom_ref, atom.next_atom_ref,945 atom.prev_atom_ref, atom.next_atom_ref,
948 });946 });
949 if (atom.fdes(elf_file).len > 0) {947 if (atom.file(elf_file)) |atom_file| switch (atom_file) {
950 try writer.writeAll(" : fdes{ ");948 .object => |object| {
951 const extras = atom.extra(elf_file);949 if (atom.fdes(object).len > 0) {
952 for (atom.fdes(elf_file), extras.fde_start..) |fde, i| {950 try writer.writeAll(" : fdes{ ");
953 try writer.print("{d}", .{i});951 const extras = atom.extra(elf_file);
954 if (!fde.alive) try writer.writeAll("([*])");952 for (atom.fdes(object), extras.fde_start..) |fde, i| {
955 if (i - extras.fde_start < extras.fde_count - 1) try writer.writeAll(", ");953 try writer.print("{d}", .{i});
956 }954 if (!fde.alive) try writer.writeAll("([*])");
957 try writer.writeAll(" }");955 if (i - extras.fde_start < extras.fde_count - 1) try writer.writeAll(", ");
958 }956 }
957 try writer.writeAll(" }");
958 }
959 },
960 else => {},
961 };
959 if (!atom.alive) {962 if (!atom.alive) {
960 try writer.writeAll(" : [*]");963 try writer.writeAll(" : [*]");
961 }964 }
src/link/Elf/Object.zig+197-126
...@@ -37,72 +37,87 @@ num_dynrelocs: u32 = 0,...@@ -37,72 +37,87 @@ num_dynrelocs: u32 = 0,
37output_symtab_ctx: Elf.SymtabCtx = .{},37output_symtab_ctx: Elf.SymtabCtx = .{},
38output_ar_state: Archive.ArState = .{},38output_ar_state: Archive.ArState = .{},
3939
40pub fn deinit(self: *Object, allocator: Allocator) void {40pub fn deinit(self: *Object, gpa: Allocator) void {
41 if (self.archive) |*ar| allocator.free(ar.path.sub_path);41 if (self.archive) |*ar| gpa.free(ar.path.sub_path);
42 allocator.free(self.path.sub_path);42 gpa.free(self.path.sub_path);
43 self.shdrs.deinit(allocator);43 self.shdrs.deinit(gpa);
44 self.symtab.deinit(allocator);44 self.symtab.deinit(gpa);
45 self.strtab.deinit(allocator);45 self.strtab.deinit(gpa);
46 self.symbols.deinit(allocator);46 self.symbols.deinit(gpa);
47 self.symbols_extra.deinit(allocator);47 self.symbols_extra.deinit(gpa);
48 self.symbols_resolver.deinit(allocator);48 self.symbols_resolver.deinit(gpa);
49 self.atoms.deinit(allocator);49 self.atoms.deinit(gpa);
50 self.atoms_indexes.deinit(allocator);50 self.atoms_indexes.deinit(gpa);
51 self.atoms_extra.deinit(allocator);51 self.atoms_extra.deinit(gpa);
52 self.comdat_groups.deinit(allocator);52 self.comdat_groups.deinit(gpa);
53 self.comdat_group_data.deinit(allocator);53 self.comdat_group_data.deinit(gpa);
54 self.relocs.deinit(allocator);54 self.relocs.deinit(gpa);
55 self.fdes.deinit(allocator);55 self.fdes.deinit(gpa);
56 self.cies.deinit(allocator);56 self.cies.deinit(gpa);
57 self.eh_frame_data.deinit(allocator);57 self.eh_frame_data.deinit(gpa);
58 for (self.input_merge_sections.items) |*isec| {58 for (self.input_merge_sections.items) |*isec| {
59 isec.deinit(allocator);59 isec.deinit(gpa);
60 }60 }
61 self.input_merge_sections.deinit(allocator);61 self.input_merge_sections.deinit(gpa);
62 self.input_merge_sections_indexes.deinit(allocator);62 self.input_merge_sections_indexes.deinit(gpa);
63}63}
6464
65pub fn parse(self: *Object, elf_file: *Elf) !void {65pub fn parse(
66 const gpa = elf_file.base.comp.gpa;66 self: *Object,
67 const cpu_arch = elf_file.getTarget().cpu.arch;67 gpa: Allocator,
68 const handle = elf_file.fileHandle(self.file_handle);68 diags: *Diags,
6969 /// For error reporting purposes only.
70 try self.parseCommon(gpa, handle, elf_file);70 path: Path,
71 handle: fs.File,
72 first_eflags: *?elf.Word,
73 target: std.Target,
74 debug_fmt_strip: bool,
75 default_sym_version: elf.Versym,
76) !void {
77 try self.parseCommon(gpa, diags, path, handle, first_eflags, target);
7178
72 // Append null input merge section79 // Append null input merge section
73 try self.input_merge_sections.append(gpa, .{});80 try self.input_merge_sections.append(gpa, .{});
74 // Allocate atom index 0 to null atom81 // Allocate atom index 0 to null atom
75 try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) });82 try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) });
7683
77 try self.initAtoms(gpa, handle, elf_file);84 try self.initAtoms(gpa, diags, path, handle, debug_fmt_strip, target);
78 try self.initSymbols(gpa, elf_file);85 try self.initSymbols(gpa, default_sym_version);
7986
80 for (self.shdrs.items, 0..) |shdr, i| {87 for (self.shdrs.items, 0..) |shdr, i| {
81 const atom_ptr = self.atom(self.atoms_indexes.items[i]) orelse continue;88 const atom_ptr = self.atom(self.atoms_indexes.items[i]) orelse continue;
82 if (!atom_ptr.alive) continue;89 if (!atom_ptr.alive) continue;
83 if ((cpu_arch == .x86_64 and shdr.sh_type == elf.SHT_X86_64_UNWIND) or90 if ((target.cpu.arch == .x86_64 and shdr.sh_type == elf.SHT_X86_64_UNWIND) or
84 mem.eql(u8, atom_ptr.name(elf_file), ".eh_frame"))91 mem.eql(u8, self.getString(atom_ptr.name_offset), ".eh_frame"))
85 {92 {
86 try self.parseEhFrame(gpa, handle, @as(u32, @intCast(i)), elf_file);93 try self.parseEhFrame(gpa, handle, @intCast(i), target);
87 }94 }
88 }95 }
89}96}
9097
91fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: *Elf) !void {98fn parseCommon(
99 self: *Object,
100 gpa: Allocator,
101 diags: *Diags,
102 path: Path,
103 handle: fs.File,
104 first_eflags: *?elf.Word,
105 target: std.Target,
106) !void {
92 const offset = if (self.archive) |ar| ar.offset else 0;107 const offset = if (self.archive) |ar| ar.offset else 0;
93 const file_size = (try handle.stat()).size;108 const file_size = (try handle.stat()).size;
94109
95 const header_buffer = try Elf.preadAllAlloc(allocator, handle, offset, @sizeOf(elf.Elf64_Ehdr));110 const header_buffer = try Elf.preadAllAlloc(gpa, handle, offset, @sizeOf(elf.Elf64_Ehdr));
96 defer allocator.free(header_buffer);111 defer gpa.free(header_buffer);
97 self.header = @as(*align(1) const elf.Elf64_Ehdr, @ptrCast(header_buffer)).*;112 self.header = @as(*align(1) const elf.Elf64_Ehdr, @ptrCast(header_buffer)).*;
98113
99 const em = elf_file.base.comp.root_mod.resolved_target.result.toElfMachine();114 const em = target.toElfMachine();
100 if (em != self.header.?.e_machine) {115 if (em != self.header.?.e_machine) {
101 return elf_file.failFile(self.index, "invalid ELF machine type: {s}", .{116 return diags.failParse(path, "invalid ELF machine type: {s}", .{
102 @tagName(self.header.?.e_machine),117 @tagName(self.header.?.e_machine),
103 });118 });
104 }119 }
105 try elf_file.validateEFlags(self.index, self.header.?.e_flags);120 try validateEFlags(diags, path, target, self.header.?.e_flags, first_eflags);
106121
107 if (self.header.?.e_shnum == 0) return;122 if (self.header.?.e_shnum == 0) return;
108123
...@@ -110,30 +125,30 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil...@@ -110,30 +125,30 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil
110 const shnum = math.cast(usize, self.header.?.e_shnum) orelse return error.Overflow;125 const shnum = math.cast(usize, self.header.?.e_shnum) orelse return error.Overflow;
111 const shsize = shnum * @sizeOf(elf.Elf64_Shdr);126 const shsize = shnum * @sizeOf(elf.Elf64_Shdr);
112 if (file_size < offset + shoff or file_size < offset + shoff + shsize) {127 if (file_size < offset + shoff or file_size < offset + shoff + shsize) {
113 return elf_file.failFile(self.index, "corrupt header: section header table extends past the end of file", .{});128 return diags.failParse(path, "corrupt header: section header table extends past the end of file", .{});
114 }129 }
115130
116 const shdrs_buffer = try Elf.preadAllAlloc(allocator, handle, offset + shoff, shsize);131 const shdrs_buffer = try Elf.preadAllAlloc(gpa, handle, offset + shoff, shsize);
117 defer allocator.free(shdrs_buffer);132 defer gpa.free(shdrs_buffer);
118 const shdrs = @as([*]align(1) const elf.Elf64_Shdr, @ptrCast(shdrs_buffer.ptr))[0..shnum];133 const shdrs = @as([*]align(1) const elf.Elf64_Shdr, @ptrCast(shdrs_buffer.ptr))[0..shnum];
119 try self.shdrs.appendUnalignedSlice(allocator, shdrs);134 try self.shdrs.appendUnalignedSlice(gpa, shdrs);
120135
121 for (self.shdrs.items) |shdr| {136 for (self.shdrs.items) |shdr| {
122 if (shdr.sh_type != elf.SHT_NOBITS) {137 if (shdr.sh_type != elf.SHT_NOBITS) {
123 if (file_size < offset + shdr.sh_offset or file_size < offset + shdr.sh_offset + shdr.sh_size) {138 if (file_size < offset + shdr.sh_offset or file_size < offset + shdr.sh_offset + shdr.sh_size) {
124 return elf_file.failFile(self.index, "corrupt section: extends past the end of file", .{});139 return diags.failParse(path, "corrupt section: extends past the end of file", .{});
125 }140 }
126 }141 }
127 }142 }
128143
129 const shstrtab = try self.preadShdrContentsAlloc(allocator, handle, self.header.?.e_shstrndx);144 const shstrtab = try self.preadShdrContentsAlloc(gpa, handle, self.header.?.e_shstrndx);
130 defer allocator.free(shstrtab);145 defer gpa.free(shstrtab);
131 for (self.shdrs.items) |shdr| {146 for (self.shdrs.items) |shdr| {
132 if (shdr.sh_name >= shstrtab.len) {147 if (shdr.sh_name >= shstrtab.len) {
133 return elf_file.failFile(self.index, "corrupt section name offset", .{});148 return diags.failParse(path, "corrupt section name offset", .{});
134 }149 }
135 }150 }
136 try self.strtab.appendSlice(allocator, shstrtab);151 try self.strtab.appendSlice(gpa, shstrtab);
137152
138 const symtab_index = for (self.shdrs.items, 0..) |shdr, i| switch (shdr.sh_type) {153 const symtab_index = for (self.shdrs.items, 0..) |shdr, i| switch (shdr.sh_type) {
139 elf.SHT_SYMTAB => break @as(u32, @intCast(i)),154 elf.SHT_SYMTAB => break @as(u32, @intCast(i)),
...@@ -144,19 +159,19 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil...@@ -144,19 +159,19 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil
144 const shdr = self.shdrs.items[index];159 const shdr = self.shdrs.items[index];
145 self.first_global = shdr.sh_info;160 self.first_global = shdr.sh_info;
146161
147 const raw_symtab = try self.preadShdrContentsAlloc(allocator, handle, index);162 const raw_symtab = try self.preadShdrContentsAlloc(gpa, handle, index);
148 defer allocator.free(raw_symtab);163 defer gpa.free(raw_symtab);
149 const nsyms = math.divExact(usize, raw_symtab.len, @sizeOf(elf.Elf64_Sym)) catch {164 const nsyms = math.divExact(usize, raw_symtab.len, @sizeOf(elf.Elf64_Sym)) catch {
150 return elf_file.failFile(self.index, "symbol table not evenly divisible", .{});165 return diags.failParse(path, "symbol table not evenly divisible", .{});
151 };166 };
152 const symtab = @as([*]align(1) const elf.Elf64_Sym, @ptrCast(raw_symtab.ptr))[0..nsyms];167 const symtab = @as([*]align(1) const elf.Elf64_Sym, @ptrCast(raw_symtab.ptr))[0..nsyms];
153168
154 const strtab_bias = @as(u32, @intCast(self.strtab.items.len));169 const strtab_bias = @as(u32, @intCast(self.strtab.items.len));
155 const strtab = try self.preadShdrContentsAlloc(allocator, handle, shdr.sh_link);170 const strtab = try self.preadShdrContentsAlloc(gpa, handle, shdr.sh_link);
156 defer allocator.free(strtab);171 defer gpa.free(strtab);
157 try self.strtab.appendSlice(allocator, strtab);172 try self.strtab.appendSlice(gpa, strtab);
158173
159 try self.symtab.ensureUnusedCapacity(allocator, symtab.len);174 try self.symtab.ensureUnusedCapacity(gpa, symtab.len);
160 for (symtab) |sym| {175 for (symtab) |sym| {
161 const out_sym = self.symtab.addOneAssumeCapacity();176 const out_sym = self.symtab.addOneAssumeCapacity();
162 out_sym.* = sym;177 out_sym.* = sym;
...@@ -168,15 +183,56 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil...@@ -168,15 +183,56 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil
168 }183 }
169}184}
170185
171fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: *Elf) !void {186fn validateEFlags(
172 const comp = elf_file.base.comp;187 diags: *Diags,
173 const debug_fmt_strip = comp.config.debug_format == .strip;188 path: Path,
174 const target = comp.root_mod.resolved_target.result;189 target: std.Target,
190 e_flags: elf.Word,
191 first_eflags: *?elf.Word,
192) error{LinkFailure}!void {
193 if (first_eflags.*) |*self_eflags| {
194 switch (target.cpu.arch) {
195 .riscv64 => {
196 if (e_flags != self_eflags.*) {
197 const riscv_eflags: riscv.RiscvEflags = @bitCast(e_flags);
198 const self_riscv_eflags: *riscv.RiscvEflags = @ptrCast(self_eflags);
199
200 self_riscv_eflags.rvc = self_riscv_eflags.rvc or riscv_eflags.rvc;
201 self_riscv_eflags.tso = self_riscv_eflags.tso or riscv_eflags.tso;
202
203 var any_errors: bool = false;
204 if (self_riscv_eflags.fabi != riscv_eflags.fabi) {
205 any_errors = true;
206 diags.addParseError(path, "cannot link object files with different float-point ABIs", .{});
207 }
208 if (self_riscv_eflags.rve != riscv_eflags.rve) {
209 any_errors = true;
210 diags.addParseError(path, "cannot link object files with different RVEs", .{});
211 }
212 if (any_errors) return error.LinkFailure;
213 }
214 },
215 else => {},
216 }
217 } else {
218 first_eflags.* = e_flags;
219 }
220}
221
222fn initAtoms(
223 self: *Object,
224 gpa: Allocator,
225 diags: *Diags,
226 path: Path,
227 handle: fs.File,
228 debug_fmt_strip: bool,
229 target: std.Target,
230) !void {
175 const shdrs = self.shdrs.items;231 const shdrs = self.shdrs.items;
176 try self.atoms.ensureTotalCapacityPrecise(allocator, shdrs.len);232 try self.atoms.ensureTotalCapacityPrecise(gpa, shdrs.len);
177 try self.atoms_extra.ensureTotalCapacityPrecise(allocator, shdrs.len * @sizeOf(Atom.Extra));233 try self.atoms_extra.ensureTotalCapacityPrecise(gpa, shdrs.len * @sizeOf(Atom.Extra));
178 try self.atoms_indexes.ensureTotalCapacityPrecise(allocator, shdrs.len);234 try self.atoms_indexes.ensureTotalCapacityPrecise(gpa, shdrs.len);
179 try self.atoms_indexes.resize(allocator, shdrs.len);235 try self.atoms_indexes.resize(gpa, shdrs.len);
180 @memset(self.atoms_indexes.items, 0);236 @memset(self.atoms_indexes.items, 0);
181237
182 for (shdrs, 0..) |shdr, i| {238 for (shdrs, 0..) |shdr, i| {
...@@ -201,24 +257,24 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:...@@ -201,24 +257,24 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:
201 };257 };
202258
203 const shndx: u32 = @intCast(i);259 const shndx: u32 = @intCast(i);
204 const group_raw_data = try self.preadShdrContentsAlloc(allocator, handle, shndx);260 const group_raw_data = try self.preadShdrContentsAlloc(gpa, handle, shndx);
205 defer allocator.free(group_raw_data);261 defer gpa.free(group_raw_data);
206 const group_nmembers = math.divExact(usize, group_raw_data.len, @sizeOf(u32)) catch {262 const group_nmembers = math.divExact(usize, group_raw_data.len, @sizeOf(u32)) catch {
207 return elf_file.failFile(self.index, "corrupt section group: not evenly divisible ", .{});263 return diags.failParse(path, "corrupt section group: not evenly divisible ", .{});
208 };264 };
209 if (group_nmembers == 0) {265 if (group_nmembers == 0) {
210 return elf_file.failFile(self.index, "corrupt section group: empty section", .{});266 return diags.failParse(path, "corrupt section group: empty section", .{});
211 }267 }
212 const group_members = @as([*]align(1) const u32, @ptrCast(group_raw_data.ptr))[0..group_nmembers];268 const group_members = @as([*]align(1) const u32, @ptrCast(group_raw_data.ptr))[0..group_nmembers];
213269
214 if (group_members[0] != elf.GRP_COMDAT) {270 if (group_members[0] != elf.GRP_COMDAT) {
215 return elf_file.failFile(self.index, "corrupt section group: unknown SHT_GROUP format", .{});271 return diags.failParse(path, "corrupt section group: unknown SHT_GROUP format", .{});
216 }272 }
217273
218 const group_start: u32 = @intCast(self.comdat_group_data.items.len);274 const group_start: u32 = @intCast(self.comdat_group_data.items.len);
219 try self.comdat_group_data.appendUnalignedSlice(allocator, group_members[1..]);275 try self.comdat_group_data.appendUnalignedSlice(gpa, group_members[1..]);
220276
221 const comdat_group_index = try self.addComdatGroup(allocator);277 const comdat_group_index = try self.addComdatGroup(gpa);
222 const comdat_group = self.comdatGroup(comdat_group_index);278 const comdat_group = self.comdatGroup(comdat_group_index);
223 comdat_group.* = .{279 comdat_group.* = .{
224 .signature_off = group_signature,280 .signature_off = group_signature,
...@@ -242,8 +298,8 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:...@@ -242,8 +298,8 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:
242 const shndx: u32 = @intCast(i);298 const shndx: u32 = @intCast(i);
243 if (self.skipShdr(shndx, debug_fmt_strip)) continue;299 if (self.skipShdr(shndx, debug_fmt_strip)) continue;
244 const size, const alignment = if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) blk: {300 const size, const alignment = if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) blk: {
245 const data = try self.preadShdrContentsAlloc(allocator, handle, shndx);301 const data = try self.preadShdrContentsAlloc(gpa, handle, shndx);
246 defer allocator.free(data);302 defer gpa.free(data);
247 const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*;303 const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*;
248 break :blk .{ chdr.ch_size, Alignment.fromNonzeroByteUnits(chdr.ch_addralign) };304 break :blk .{ chdr.ch_size, Alignment.fromNonzeroByteUnits(chdr.ch_addralign) };
249 } else .{ shdr.sh_size, Alignment.fromNonzeroByteUnits(shdr.sh_addralign) };305 } else .{ shdr.sh_size, Alignment.fromNonzeroByteUnits(shdr.sh_addralign) };
...@@ -263,13 +319,13 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:...@@ -263,13 +319,13 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:
263 elf.SHT_REL, elf.SHT_RELA => {319 elf.SHT_REL, elf.SHT_RELA => {
264 const atom_index = self.atoms_indexes.items[shdr.sh_info];320 const atom_index = self.atoms_indexes.items[shdr.sh_info];
265 if (self.atom(atom_index)) |atom_ptr| {321 if (self.atom(atom_index)) |atom_ptr| {
266 const relocs = try self.preadRelocsAlloc(allocator, handle, @intCast(i));322 const relocs = try self.preadRelocsAlloc(gpa, handle, @intCast(i));
267 defer allocator.free(relocs);323 defer gpa.free(relocs);
268 atom_ptr.relocs_section_index = @intCast(i);324 atom_ptr.relocs_section_index = @intCast(i);
269 const rel_index: u32 = @intCast(self.relocs.items.len);325 const rel_index: u32 = @intCast(self.relocs.items.len);
270 const rel_count: u32 = @intCast(relocs.len);326 const rel_count: u32 = @intCast(relocs.len);
271 self.setAtomFields(atom_ptr, .{ .rel_index = rel_index, .rel_count = rel_count });327 self.setAtomFields(atom_ptr, .{ .rel_index = rel_index, .rel_count = rel_count });
272 try self.relocs.appendUnalignedSlice(allocator, relocs);328 try self.relocs.appendUnalignedSlice(gpa, relocs);
273 if (target.cpu.arch == .riscv64) {329 if (target.cpu.arch == .riscv64) {
274 sortRelocs(self.relocs.items[rel_index..][0..rel_count]);330 sortRelocs(self.relocs.items[rel_index..][0..rel_count]);
275 }331 }
...@@ -293,14 +349,18 @@ fn skipShdr(self: *Object, index: u32, debug_fmt_strip: bool) bool {...@@ -293,14 +349,18 @@ fn skipShdr(self: *Object, index: u32, debug_fmt_strip: bool) bool {
293 return ignore;349 return ignore;
294}350}
295351
296fn initSymbols(self: *Object, allocator: Allocator, elf_file: *Elf) !void {352fn initSymbols(
353 self: *Object,
354 gpa: Allocator,
355 default_sym_version: elf.Versym,
356) !void {
297 const first_global = self.first_global orelse self.symtab.items.len;357 const first_global = self.first_global orelse self.symtab.items.len;
298 const nglobals = self.symtab.items.len - first_global;358 const nglobals = self.symtab.items.len - first_global;
299359
300 try self.symbols.ensureTotalCapacityPrecise(allocator, self.symtab.items.len);360 try self.symbols.ensureTotalCapacityPrecise(gpa, self.symtab.items.len);
301 try self.symbols_extra.ensureTotalCapacityPrecise(allocator, self.symtab.items.len * @sizeOf(Symbol.Extra));361 try self.symbols_extra.ensureTotalCapacityPrecise(gpa, self.symtab.items.len * @sizeOf(Symbol.Extra));
302 try self.symbols_resolver.ensureTotalCapacityPrecise(allocator, nglobals);362 try self.symbols_resolver.ensureTotalCapacityPrecise(gpa, nglobals);
303 self.symbols_resolver.resize(allocator, nglobals) catch unreachable;363 self.symbols_resolver.resize(gpa, nglobals) catch unreachable;
304 @memset(self.symbols_resolver.items, 0);364 @memset(self.symbols_resolver.items, 0);
305365
306 for (self.symtab.items, 0..) |sym, i| {366 for (self.symtab.items, 0..) |sym, i| {
...@@ -310,7 +370,7 @@ fn initSymbols(self: *Object, allocator: Allocator, elf_file: *Elf) !void {...@@ -310,7 +370,7 @@ fn initSymbols(self: *Object, allocator: Allocator, elf_file: *Elf) !void {
310 sym_ptr.name_offset = sym.st_name;370 sym_ptr.name_offset = sym.st_name;
311 sym_ptr.esym_index = @intCast(i);371 sym_ptr.esym_index = @intCast(i);
312 sym_ptr.extra_index = self.addSymbolExtraAssumeCapacity(.{});372 sym_ptr.extra_index = self.addSymbolExtraAssumeCapacity(.{});
313 sym_ptr.version_index = if (i >= first_global) elf_file.default_sym_version else .LOCAL;373 sym_ptr.version_index = if (i >= first_global) default_sym_version else .LOCAL;
314 sym_ptr.flags.weak = sym.st_bind() == elf.STB_WEAK;374 sym_ptr.flags.weak = sym.st_bind() == elf.STB_WEAK;
315 if (sym.st_shndx != elf.SHN_ABS and sym.st_shndx != elf.SHN_COMMON) {375 if (sym.st_shndx != elf.SHN_ABS and sym.st_shndx != elf.SHN_COMMON) {
316 sym_ptr.ref = .{ .index = self.atoms_indexes.items[sym.st_shndx], .file = self.index };376 sym_ptr.ref = .{ .index = self.atoms_indexes.items[sym.st_shndx], .file = self.index };
...@@ -318,24 +378,30 @@ fn initSymbols(self: *Object, allocator: Allocator, elf_file: *Elf) !void {...@@ -318,24 +378,30 @@ fn initSymbols(self: *Object, allocator: Allocator, elf_file: *Elf) !void {
318 }378 }
319}379}
320380
321fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx: u32, elf_file: *Elf) !void {381fn parseEhFrame(
382 self: *Object,
383 gpa: Allocator,
384 handle: fs.File,
385 shndx: u32,
386 target: std.Target,
387) !void {
322 const relocs_shndx = for (self.shdrs.items, 0..) |shdr, i| switch (shdr.sh_type) {388 const relocs_shndx = for (self.shdrs.items, 0..) |shdr, i| switch (shdr.sh_type) {
323 elf.SHT_RELA => if (shdr.sh_info == shndx) break @as(u32, @intCast(i)),389 elf.SHT_RELA => if (shdr.sh_info == shndx) break @as(u32, @intCast(i)),
324 else => {},390 else => {},
325 } else null;391 } else null;
326392
327 const raw = try self.preadShdrContentsAlloc(allocator, handle, shndx);393 const raw = try self.preadShdrContentsAlloc(gpa, handle, shndx);
328 defer allocator.free(raw);394 defer gpa.free(raw);
329 const data_start = @as(u32, @intCast(self.eh_frame_data.items.len));395 const data_start: u32 = @intCast(self.eh_frame_data.items.len);
330 try self.eh_frame_data.appendSlice(allocator, raw);396 try self.eh_frame_data.appendSlice(gpa, raw);
331 const relocs = if (relocs_shndx) |index|397 const relocs = if (relocs_shndx) |index|
332 try self.preadRelocsAlloc(allocator, handle, index)398 try self.preadRelocsAlloc(gpa, handle, index)
333 else399 else
334 &[0]elf.Elf64_Rela{};400 &[0]elf.Elf64_Rela{};
335 defer allocator.free(relocs);401 defer gpa.free(relocs);
336 const rel_start = @as(u32, @intCast(self.relocs.items.len));402 const rel_start: u32 = @intCast(self.relocs.items.len);
337 try self.relocs.appendUnalignedSlice(allocator, relocs);403 try self.relocs.appendUnalignedSlice(gpa, relocs);
338 if (elf_file.getTarget().cpu.arch == .riscv64) {404 if (target.cpu.arch == .riscv64) {
339 sortRelocs(self.relocs.items[rel_start..][0..relocs.len]);405 sortRelocs(self.relocs.items[rel_start..][0..relocs.len]);
340 }406 }
341 const fdes_start = self.fdes.items.len;407 const fdes_start = self.fdes.items.len;
...@@ -345,11 +411,11 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx:...@@ -345,11 +411,11 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx:
345 while (try it.next()) |rec| {411 while (try it.next()) |rec| {
346 const rel_range = filterRelocs(self.relocs.items[rel_start..][0..relocs.len], rec.offset, rec.size + 4);412 const rel_range = filterRelocs(self.relocs.items[rel_start..][0..relocs.len], rec.offset, rec.size + 4);
347 switch (rec.tag) {413 switch (rec.tag) {
348 .cie => try self.cies.append(allocator, .{414 .cie => try self.cies.append(gpa, .{
349 .offset = data_start + rec.offset,415 .offset = data_start + rec.offset,
350 .size = rec.size,416 .size = rec.size,
351 .rel_index = rel_start + @as(u32, @intCast(rel_range.start)),417 .rel_index = rel_start + @as(u32, @intCast(rel_range.start)),
352 .rel_num = @as(u32, @intCast(rel_range.len)),418 .rel_num = @intCast(rel_range.len),
353 .input_section_index = shndx,419 .input_section_index = shndx,
354 .file_index = self.index,420 .file_index = self.index,
355 }),421 }),
...@@ -361,12 +427,12 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx:...@@ -361,12 +427,12 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx:
361 // this can happen for object files built with -r flag by the linker.427 // this can happen for object files built with -r flag by the linker.
362 continue;428 continue;
363 }429 }
364 try self.fdes.append(allocator, .{430 try self.fdes.append(gpa, .{
365 .offset = data_start + rec.offset,431 .offset = data_start + rec.offset,
366 .size = rec.size,432 .size = rec.size,
367 .cie_index = undefined,433 .cie_index = undefined,
368 .rel_index = rel_start + @as(u32, @intCast(rel_range.start)),434 .rel_index = rel_start + @as(u32, @intCast(rel_range.start)),
369 .rel_num = @as(u32, @intCast(rel_range.len)),435 .rel_num = @intCast(rel_range.len),
370 .input_section_index = shndx,436 .input_section_index = shndx,
371 .file_index = self.index,437 .file_index = self.index,
372 });438 });
...@@ -376,7 +442,7 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx:...@@ -376,7 +442,7 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx:
376442
377 // Tie each FDE to its CIE443 // Tie each FDE to its CIE
378 for (self.fdes.items[fdes_start..]) |*fde| {444 for (self.fdes.items[fdes_start..]) |*fde| {
379 const cie_ptr = fde.offset + 4 - fde.ciePointer(elf_file);445 const cie_ptr = fde.offset + 4 - fde.ciePointer(self);
380 const cie_index = for (self.cies.items[cies_start..], cies_start..) |cie, cie_index| {446 const cie_index = for (self.cies.items[cies_start..], cies_start..) |cie, cie_index| {
381 if (cie.offset == cie_ptr) break @as(u32, @intCast(cie_index));447 if (cie.offset == cie_ptr) break @as(u32, @intCast(cie_index));
382 } else {448 } else {
...@@ -392,26 +458,26 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx:...@@ -392,26 +458,26 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx:
392458
393 // Tie each FDE record to its matching atom459 // Tie each FDE record to its matching atom
394 const SortFdes = struct {460 const SortFdes = struct {
395 pub fn lessThan(ctx: *Elf, lhs: Fde, rhs: Fde) bool {461 pub fn lessThan(ctx: *Object, lhs: Fde, rhs: Fde) bool {
396 const lhs_atom = lhs.atom(ctx);462 const lhs_atom = lhs.atom(ctx);
397 const rhs_atom = rhs.atom(ctx);463 const rhs_atom = rhs.atom(ctx);
398 return lhs_atom.priority(ctx) < rhs_atom.priority(ctx);464 return Atom.priorityLookup(ctx.index, lhs_atom.input_section_index) < Atom.priorityLookup(ctx.index, rhs_atom.input_section_index);
399 }465 }
400 };466 };
401 mem.sort(Fde, self.fdes.items[fdes_start..], elf_file, SortFdes.lessThan);467 mem.sort(Fde, self.fdes.items[fdes_start..], self, SortFdes.lessThan);
402468
403 // Create a back-link from atom to FDEs469 // Create a back-link from atom to FDEs
404 var i: u32 = @as(u32, @intCast(fdes_start));470 var i: u32 = @intCast(fdes_start);
405 while (i < self.fdes.items.len) {471 while (i < self.fdes.items.len) {
406 const fde = self.fdes.items[i];472 const fde = self.fdes.items[i];
407 const atom_ptr = fde.atom(elf_file);473 const atom_ptr = fde.atom(self);
408 const start = i;474 const start = i;
409 i += 1;475 i += 1;
410 while (i < self.fdes.items.len) : (i += 1) {476 while (i < self.fdes.items.len) : (i += 1) {
411 const next_fde = self.fdes.items[i];477 const next_fde = self.fdes.items[i];
412 if (atom_ptr.atom_index != next_fde.atom(elf_file).atom_index) break;478 if (atom_ptr.atom_index != next_fde.atom(self).atom_index) break;
413 }479 }
414 atom_ptr.addExtra(.{ .fde_start = start, .fde_count = i - start }, elf_file);480 self.setAtomFields(atom_ptr, .{ .fde_start = start, .fde_count = i - start });
415 }481 }
416}482}
417483
...@@ -904,7 +970,7 @@ pub fn markComdatGroupsDead(self: *Object, elf_file: *Elf) void {...@@ -904,7 +970,7 @@ pub fn markComdatGroupsDead(self: *Object, elf_file: *Elf) void {
904 const atom_index = self.atoms_indexes.items[shndx];970 const atom_index = self.atoms_indexes.items[shndx];
905 if (self.atom(atom_index)) |atom_ptr| {971 if (self.atom(atom_index)) |atom_ptr| {
906 atom_ptr.alive = false;972 atom_ptr.alive = false;
907 atom_ptr.markFdesDead(elf_file);973 atom_ptr.markFdesDead(self);
908 }974 }
909 }975 }
910 }976 }
...@@ -970,10 +1036,13 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void {...@@ -970,10 +1036,13 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void {
970 }1036 }
971}1037}
9721038
973pub fn parseAr(self: *Object, elf_file: *Elf) !void {1039pub fn parseAr(self: *Object, path: Path, elf_file: *Elf) !void {
974 const gpa = elf_file.base.comp.gpa;1040 const gpa = elf_file.base.comp.gpa;
1041 const diags = &elf_file.base.comp.link_diags;
975 const handle = elf_file.fileHandle(self.file_handle);1042 const handle = elf_file.fileHandle(self.file_handle);
976 try self.parseCommon(gpa, handle, elf_file);1043 const first_eflags = &elf_file.first_eflags;
1044 const target = elf_file.base.comp.root_mod.resolved_target.result;
1045 try self.parseCommon(gpa, diags, path, handle, first_eflags, target);
977}1046}
9781047
979pub fn updateArSymtab(self: Object, ar_symtab: *Archive.ArSymtab, elf_file: *Elf) !void {1048pub fn updateArSymtab(self: Object, ar_symtab: *Archive.ArSymtab, elf_file: *Elf) !void {
...@@ -1000,7 +1069,7 @@ pub fn updateArSize(self: *Object, elf_file: *Elf) !void {...@@ -1000,7 +1069,7 @@ pub fn updateArSize(self: *Object, elf_file: *Elf) !void {
1000pub fn writeAr(self: Object, elf_file: *Elf, writer: anytype) !void {1069pub fn writeAr(self: Object, elf_file: *Elf, writer: anytype) !void {
1001 const size = std.math.cast(usize, self.output_ar_state.size) orelse return error.Overflow;1070 const size = std.math.cast(usize, self.output_ar_state.size) orelse return error.Overflow;
1002 const offset: u64 = if (self.archive) |ar| ar.offset else 0;1071 const offset: u64 = if (self.archive) |ar| ar.offset else 0;
1003 const name = std.fs.path.basename(self.path.sub_path);1072 const name = fs.path.basename(self.path.sub_path);
1004 const hdr = Archive.setArHdr(.{1073 const hdr = Archive.setArHdr(.{
1005 .name = if (name.len <= Archive.max_member_name_len)1074 .name = if (name.len <= Archive.max_member_name_len)
1006 .{ .name = name }1075 .{ .name = name }
...@@ -1136,8 +1205,8 @@ pub fn resolveSymbol(self: Object, index: Symbol.Index, elf_file: *Elf) Elf.Ref...@@ -1136,8 +1205,8 @@ pub fn resolveSymbol(self: Object, index: Symbol.Index, elf_file: *Elf) Elf.Ref
1136 return elf_file.resolver.get(resolv).?;1205 return elf_file.resolver.get(resolv).?;
1137}1206}
11381207
1139fn addSymbol(self: *Object, allocator: Allocator) !Symbol.Index {1208fn addSymbol(self: *Object, gpa: Allocator) !Symbol.Index {
1140 try self.symbols.ensureUnusedCapacity(allocator, 1);1209 try self.symbols.ensureUnusedCapacity(gpa, 1);
1141 return self.addSymbolAssumeCapacity();1210 return self.addSymbolAssumeCapacity();
1142}1211}
11431212
...@@ -1147,9 +1216,9 @@ fn addSymbolAssumeCapacity(self: *Object) Symbol.Index {...@@ -1147,9 +1216,9 @@ fn addSymbolAssumeCapacity(self: *Object) Symbol.Index {
1147 return index;1216 return index;
1148}1217}
11491218
1150pub fn addSymbolExtra(self: *Object, allocator: Allocator, extra: Symbol.Extra) !u32 {1219pub fn addSymbolExtra(self: *Object, gpa: Allocator, extra: Symbol.Extra) !u32 {
1151 const fields = @typeInfo(Symbol.Extra).@"struct".fields;1220 const fields = @typeInfo(Symbol.Extra).@"struct".fields;
1152 try self.symbols_extra.ensureUnusedCapacity(allocator, fields.len);1221 try self.symbols_extra.ensureUnusedCapacity(gpa, fields.len);
1153 return self.addSymbolExtraAssumeCapacity(extra);1222 return self.addSymbolExtraAssumeCapacity(extra);
1154}1223}
11551224
...@@ -1198,27 +1267,27 @@ pub fn getString(self: Object, off: u32) [:0]const u8 {...@@ -1198,27 +1267,27 @@ pub fn getString(self: Object, off: u32) [:0]const u8 {
1198 return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.items.ptr + off)), 0);1267 return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.items.ptr + off)), 0);
1199}1268}
12001269
1201fn addString(self: *Object, allocator: Allocator, str: []const u8) !u32 {1270fn addString(self: *Object, gpa: Allocator, str: []const u8) !u32 {
1202 const off: u32 = @intCast(self.strtab.items.len);1271 const off: u32 = @intCast(self.strtab.items.len);
1203 try self.strtab.ensureUnusedCapacity(allocator, str.len + 1);1272 try self.strtab.ensureUnusedCapacity(gpa, str.len + 1);
1204 self.strtab.appendSliceAssumeCapacity(str);1273 self.strtab.appendSliceAssumeCapacity(str);
1205 self.strtab.appendAssumeCapacity(0);1274 self.strtab.appendAssumeCapacity(0);
1206 return off;1275 return off;
1207}1276}
12081277
1209/// Caller owns the memory.1278/// Caller owns the memory.
1210fn preadShdrContentsAlloc(self: Object, allocator: Allocator, handle: std.fs.File, index: u32) ![]u8 {1279fn preadShdrContentsAlloc(self: Object, gpa: Allocator, handle: fs.File, index: u32) ![]u8 {
1211 assert(index < self.shdrs.items.len);1280 assert(index < self.shdrs.items.len);
1212 const offset = if (self.archive) |ar| ar.offset else 0;1281 const offset = if (self.archive) |ar| ar.offset else 0;
1213 const shdr = self.shdrs.items[index];1282 const shdr = self.shdrs.items[index];
1214 const sh_offset = math.cast(u64, shdr.sh_offset) orelse return error.Overflow;1283 const sh_offset = math.cast(u64, shdr.sh_offset) orelse return error.Overflow;
1215 const sh_size = math.cast(u64, shdr.sh_size) orelse return error.Overflow;1284 const sh_size = math.cast(u64, shdr.sh_size) orelse return error.Overflow;
1216 return Elf.preadAllAlloc(allocator, handle, offset + sh_offset, sh_size);1285 return Elf.preadAllAlloc(gpa, handle, offset + sh_offset, sh_size);
1217}1286}
12181287
1219/// Caller owns the memory.1288/// Caller owns the memory.
1220fn preadRelocsAlloc(self: Object, allocator: Allocator, handle: std.fs.File, shndx: u32) ![]align(1) const elf.Elf64_Rela {1289fn preadRelocsAlloc(self: Object, gpa: Allocator, handle: fs.File, shndx: u32) ![]align(1) const elf.Elf64_Rela {
1221 const raw = try self.preadShdrContentsAlloc(allocator, handle, shndx);1290 const raw = try self.preadShdrContentsAlloc(gpa, handle, shndx);
1222 const num = @divExact(raw.len, @sizeOf(elf.Elf64_Rela));1291 const num = @divExact(raw.len, @sizeOf(elf.Elf64_Rela));
1223 return @as([*]align(1) const elf.Elf64_Rela, @ptrCast(raw.ptr))[0..num];1292 return @as([*]align(1) const elf.Elf64_Rela, @ptrCast(raw.ptr))[0..num];
1224}1293}
...@@ -1230,9 +1299,9 @@ const AddAtomArgs = struct {...@@ -1230,9 +1299,9 @@ const AddAtomArgs = struct {
1230 alignment: Alignment,1299 alignment: Alignment,
1231};1300};
12321301
1233fn addAtom(self: *Object, allocator: Allocator, args: AddAtomArgs) !Atom.Index {1302fn addAtom(self: *Object, gpa: Allocator, args: AddAtomArgs) !Atom.Index {
1234 try self.atoms.ensureUnusedCapacity(allocator, 1);1303 try self.atoms.ensureUnusedCapacity(gpa, 1);
1235 try self.atoms_extra.ensureUnusedCapacity(allocator, @sizeOf(Atom.Extra));1304 try self.atoms_extra.ensureUnusedCapacity(gpa, @sizeOf(Atom.Extra));
1236 return self.addAtomAssumeCapacity(args);1305 return self.addAtomAssumeCapacity(args);
1237}1306}
12381307
...@@ -1257,9 +1326,9 @@ pub fn atom(self: *Object, atom_index: Atom.Index) ?*Atom {...@@ -1257,9 +1326,9 @@ pub fn atom(self: *Object, atom_index: Atom.Index) ?*Atom {
1257 return &self.atoms.items[atom_index];1326 return &self.atoms.items[atom_index];
1258}1327}
12591328
1260pub fn addAtomExtra(self: *Object, allocator: Allocator, extra: Atom.Extra) !u32 {1329pub fn addAtomExtra(self: *Object, gpa: Allocator, extra: Atom.Extra) !u32 {
1261 const fields = @typeInfo(Atom.Extra).@"struct".fields;1330 const fields = @typeInfo(Atom.Extra).@"struct".fields;
1262 try self.atoms_extra.ensureUnusedCapacity(allocator, fields.len);1331 try self.atoms_extra.ensureUnusedCapacity(gpa, fields.len);
1263 return self.addAtomExtraAssumeCapacity(extra);1332 return self.addAtomExtraAssumeCapacity(extra);
1264}1333}
12651334
...@@ -1308,9 +1377,9 @@ fn setAtomFields(o: *Object, atom_ptr: *Atom, opts: Atom.Extra.AsOptionals) void...@@ -1308,9 +1377,9 @@ fn setAtomFields(o: *Object, atom_ptr: *Atom, opts: Atom.Extra.AsOptionals) void
1308 o.setAtomExtra(atom_ptr.extra_index, extras);1377 o.setAtomExtra(atom_ptr.extra_index, extras);
1309}1378}
13101379
1311fn addInputMergeSection(self: *Object, allocator: Allocator) !Merge.InputSection.Index {1380fn addInputMergeSection(self: *Object, gpa: Allocator) !Merge.InputSection.Index {
1312 const index: Merge.InputSection.Index = @intCast(self.input_merge_sections.items.len);1381 const index: Merge.InputSection.Index = @intCast(self.input_merge_sections.items.len);
1313 const msec = try self.input_merge_sections.addOne(allocator);1382 const msec = try self.input_merge_sections.addOne(gpa);
1314 msec.* = .{};1383 msec.* = .{};
1315 return index;1384 return index;
1316}1385}
...@@ -1320,9 +1389,9 @@ fn inputMergeSection(self: *Object, index: Merge.InputSection.Index) ?*Merge.Inp...@@ -1320,9 +1389,9 @@ fn inputMergeSection(self: *Object, index: Merge.InputSection.Index) ?*Merge.Inp
1320 return &self.input_merge_sections.items[index];1389 return &self.input_merge_sections.items[index];
1321}1390}
13221391
1323fn addComdatGroup(self: *Object, allocator: Allocator) !Elf.ComdatGroup.Index {1392fn addComdatGroup(self: *Object, gpa: Allocator) !Elf.ComdatGroup.Index {
1324 const index = @as(Elf.ComdatGroup.Index, @intCast(self.comdat_groups.items.len));1393 const index = @as(Elf.ComdatGroup.Index, @intCast(self.comdat_groups.items.len));
1325 _ = try self.comdat_groups.addOne(allocator);1394 _ = try self.comdat_groups.addOne(gpa);
1326 return index;1395 return index;
1327}1396}
13281397
...@@ -1516,8 +1585,9 @@ const log = std.log.scoped(.link);...@@ -1516,8 +1585,9 @@ const log = std.log.scoped(.link);
1516const math = std.math;1585const math = std.math;
1517const mem = std.mem;1586const mem = std.mem;
1518const Path = std.Build.Cache.Path;1587const Path = std.Build.Cache.Path;
1519const Allocator = mem.Allocator;1588const Allocator = std.mem.Allocator;
15201589
1590const Diags = @import("../../link.zig").Diags;
1521const Archive = @import("Archive.zig");1591const Archive = @import("Archive.zig");
1522const Atom = @import("Atom.zig");1592const Atom = @import("Atom.zig");
1523const AtomList = @import("AtomList.zig");1593const AtomList = @import("AtomList.zig");
...@@ -1528,3 +1598,4 @@ const File = @import("file.zig").File;...@@ -1528,3 +1598,4 @@ const File = @import("file.zig").File;
1528const Merge = @import("Merge.zig");1598const Merge = @import("Merge.zig");
1529const Symbol = @import("Symbol.zig");1599const Symbol = @import("Symbol.zig");
1530const Alignment = Atom.Alignment;1600const Alignment = Atom.Alignment;
1601const riscv = @import("../riscv.zig");
src/link/Elf/eh_frame.zig+17-20
...@@ -19,18 +19,16 @@ pub const Fde = struct {...@@ -19,18 +19,16 @@ pub const Fde = struct {
19 return base + fde.out_offset;19 return base + fde.out_offset;
20 }20 }
2121
22 pub fn data(fde: Fde, elf_file: *Elf) []u8 {22 pub fn data(fde: Fde, object: *Object) []u8 {
23 const object = elf_file.file(fde.file_index).?.object;
24 return object.eh_frame_data.items[fde.offset..][0..fde.calcSize()];23 return object.eh_frame_data.items[fde.offset..][0..fde.calcSize()];
25 }24 }
2625
27 pub fn cie(fde: Fde, elf_file: *Elf) Cie {26 pub fn cie(fde: Fde, object: *Object) Cie {
28 const object = elf_file.file(fde.file_index).?.object;
29 return object.cies.items[fde.cie_index];27 return object.cies.items[fde.cie_index];
30 }28 }
3129
32 pub fn ciePointer(fde: Fde, elf_file: *Elf) u32 {30 pub fn ciePointer(fde: Fde, object: *Object) u32 {
33 const fde_data = fde.data(elf_file);31 const fde_data = fde.data(object);
34 return std.mem.readInt(u32, fde_data[4..8], .little);32 return std.mem.readInt(u32, fde_data[4..8], .little);
35 }33 }
3634
...@@ -38,16 +36,14 @@ pub const Fde = struct {...@@ -38,16 +36,14 @@ pub const Fde = struct {
38 return fde.size + 4;36 return fde.size + 4;
39 }37 }
4038
41 pub fn atom(fde: Fde, elf_file: *Elf) *Atom {39 pub fn atom(fde: Fde, object: *Object) *Atom {
42 const object = elf_file.file(fde.file_index).?.object;40 const rel = fde.relocs(object)[0];
43 const rel = fde.relocs(elf_file)[0];
44 const sym = object.symtab.items[rel.r_sym()];41 const sym = object.symtab.items[rel.r_sym()];
45 const atom_index = object.atoms_indexes.items[sym.st_shndx];42 const atom_index = object.atoms_indexes.items[sym.st_shndx];
46 return object.atom(atom_index).?;43 return object.atom(atom_index).?;
47 }44 }
4845
49 pub fn relocs(fde: Fde, elf_file: *Elf) []align(1) const elf.Elf64_Rela {46 pub fn relocs(fde: Fde, object: *Object) []const elf.Elf64_Rela {
50 const object = elf_file.file(fde.file_index).?.object;
51 return object.relocs.items[fde.rel_index..][0..fde.rel_num];47 return object.relocs.items[fde.rel_index..][0..fde.rel_num];
52 }48 }
5349
...@@ -87,7 +83,8 @@ pub const Fde = struct {...@@ -87,7 +83,8 @@ pub const Fde = struct {
87 const fde = ctx.fde;83 const fde = ctx.fde;
88 const elf_file = ctx.elf_file;84 const elf_file = ctx.elf_file;
89 const base_addr = fde.address(elf_file);85 const base_addr = fde.address(elf_file);
90 const atom_name = fde.atom(elf_file).name(elf_file);86 const object = elf_file.file(fde.file_index).?.object;
87 const atom_name = fde.atom(object).name(elf_file);
91 try writer.print("@{x} : size({x}) : cie({d}) : {s}", .{88 try writer.print("@{x} : size({x}) : cie({d}) : {s}", .{
92 base_addr + fde.out_offset,89 base_addr + fde.out_offset,
93 fde.calcSize(),90 fde.calcSize(),
...@@ -306,7 +303,7 @@ pub fn calcEhFrameRelocs(elf_file: *Elf) usize {...@@ -306,7 +303,7 @@ pub fn calcEhFrameRelocs(elf_file: *Elf) usize {
306 }303 }
307 for (object.fdes.items) |fde| {304 for (object.fdes.items) |fde| {
308 if (!fde.alive) continue;305 if (!fde.alive) continue;
309 count += fde.relocs(elf_file).len;306 count += fde.relocs(object).len;
310 }307 }
311 }308 }
312 return count;309 return count;
...@@ -369,16 +366,16 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {...@@ -369,16 +366,16 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
369 for (object.fdes.items) |fde| {366 for (object.fdes.items) |fde| {
370 if (!fde.alive) continue;367 if (!fde.alive) continue;
371368
372 const contents = fde.data(elf_file);369 const contents = fde.data(object);
373370
374 std.mem.writeInt(371 std.mem.writeInt(
375 i32,372 i32,
376 contents[4..8],373 contents[4..8],
377 @truncate(@as(i64, @intCast(fde.out_offset + 4)) - @as(i64, @intCast(fde.cie(elf_file).out_offset))),374 @truncate(@as(i64, @intCast(fde.out_offset + 4)) - @as(i64, @intCast(fde.cie(object).out_offset))),
378 .little,375 .little,
379 );376 );
380377
381 for (fde.relocs(elf_file)) |rel| {378 for (fde.relocs(object)) |rel| {
382 const ref = object.resolveSymbol(rel.r_sym(), elf_file);379 const ref = object.resolveSymbol(rel.r_sym(), elf_file);
383 const sym = elf_file.symbol(ref).?;380 const sym = elf_file.symbol(ref).?;
384 resolveReloc(fde, sym, rel, elf_file, contents) catch |err| switch (err) {381 resolveReloc(fde, sym, rel, elf_file, contents) catch |err| switch (err) {
...@@ -412,12 +409,12 @@ pub fn writeEhFrameRelocatable(elf_file: *Elf, writer: anytype) !void {...@@ -412,12 +409,12 @@ pub fn writeEhFrameRelocatable(elf_file: *Elf, writer: anytype) !void {
412 for (object.fdes.items) |fde| {409 for (object.fdes.items) |fde| {
413 if (!fde.alive) continue;410 if (!fde.alive) continue;
414411
415 const contents = fde.data(elf_file);412 const contents = fde.data(object);
416413
417 std.mem.writeInt(414 std.mem.writeInt(
418 i32,415 i32,
419 contents[4..8],416 contents[4..8],
420 @truncate(@as(i64, @intCast(fde.out_offset + 4)) - @as(i64, @intCast(fde.cie(elf_file).out_offset))),417 @truncate(@as(i64, @intCast(fde.out_offset + 4)) - @as(i64, @intCast(fde.cie(object).out_offset))),
421 .little,418 .little,
422 );419 );
423420
...@@ -490,7 +487,7 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {...@@ -490,7 +487,7 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {
490487
491 for (object.fdes.items) |fde| {488 for (object.fdes.items) |fde| {
492 if (!fde.alive) continue;489 if (!fde.alive) continue;
493 for (fde.relocs(elf_file)) |rel| {490 for (fde.relocs(object)) |rel| {
494 const ref = object.resolveSymbol(rel.r_sym(), elf_file);491 const ref = object.resolveSymbol(rel.r_sym(), elf_file);
495 const sym = elf_file.symbol(ref).?;492 const sym = elf_file.symbol(ref).?;
496 const r_offset = fde.address(elf_file) + rel.r_offset - fde.offset;493 const r_offset = fde.address(elf_file) + rel.r_offset - fde.offset;
...@@ -548,7 +545,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void {...@@ -548,7 +545,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void {
548 for (object.fdes.items) |fde| {545 for (object.fdes.items) |fde| {
549 if (!fde.alive) continue;546 if (!fde.alive) continue;
550547
551 const relocs = fde.relocs(elf_file);548 const relocs = fde.relocs(object);
552 assert(relocs.len > 0); // Should this be an error? Things are completely broken anyhow if this trips...549 assert(relocs.len > 0); // Should this be an error? Things are completely broken anyhow if this trips...
553 const rel = relocs[0];550 const rel = relocs[0];
554 const ref = object.resolveSymbol(rel.r_sym(), elf_file);551 const ref = object.resolveSymbol(rel.r_sym(), elf_file);
src/link/Elf/gc.zig+28-21
...@@ -103,15 +103,20 @@ fn markLive(atom: *Atom, elf_file: *Elf) void {...@@ -103,15 +103,20 @@ fn markLive(atom: *Atom, elf_file: *Elf) void {
103 assert(atom.visited);103 assert(atom.visited);
104 const file = atom.file(elf_file).?;104 const file = atom.file(elf_file).?;
105105
106 for (atom.fdes(elf_file)) |fde| {106 switch (file) {
107 for (fde.relocs(elf_file)[1..]) |rel| {107 .object => |object| {
108 const ref = file.resolveSymbol(rel.r_sym(), elf_file);108 for (atom.fdes(object)) |fde| {
109 const target_sym = elf_file.symbol(ref) orelse continue;109 for (fde.relocs(object)[1..]) |rel| {
110 const target_atom = target_sym.atom(elf_file) orelse continue;110 const ref = file.resolveSymbol(rel.r_sym(), elf_file);
111 target_atom.alive = true;111 const target_sym = elf_file.symbol(ref) orelse continue;
112 gc_track_live_log.debug("{}marking live atom({d})", .{ track_live_level, target_atom.atom_index });112 const target_atom = target_sym.atom(elf_file) orelse continue;
113 if (markAtom(target_atom)) markLive(target_atom, elf_file);113 target_atom.alive = true;
114 }114 gc_track_live_log.debug("{}marking live atom({d})", .{ track_live_level, target_atom.atom_index });
115 if (markAtom(target_atom)) markLive(target_atom, elf_file);
116 }
117 }
118 },
119 else => {},
115 }120 }
116121
117 for (atom.relocs(elf_file)) |rel| {122 for (atom.relocs(elf_file)) |rel| {
...@@ -135,23 +140,25 @@ fn mark(roots: std.ArrayList(*Atom), elf_file: *Elf) void {...@@ -135,23 +140,25 @@ fn mark(roots: std.ArrayList(*Atom), elf_file: *Elf) void {
135 }140 }
136}141}
137142
138fn prune(elf_file: *Elf) void {143fn pruneInFile(file: File) void {
139 const pruneInFile = struct {144 for (file.atoms()) |atom_index| {
140 fn pruneInFile(file: File, ef: *Elf) void {145 const atom = file.atom(atom_index) orelse continue;
141 for (file.atoms()) |atom_index| {146 if (atom.alive and !atom.visited) {
142 const atom = file.atom(atom_index) orelse continue;147 atom.alive = false;
143 if (atom.alive and !atom.visited) {148 switch (file) {
144 atom.alive = false;149 .object => |object| atom.markFdesDead(object),
145 atom.markFdesDead(ef);150 else => {},
146 }
147 }151 }
148 }152 }
149 }.pruneInFile;153 }
154}
155
156fn prune(elf_file: *Elf) void {
150 if (elf_file.zigObjectPtr()) |zo| {157 if (elf_file.zigObjectPtr()) |zo| {
151 pruneInFile(zo.asFile(), elf_file);158 pruneInFile(zo.asFile());
152 }159 }
153 for (elf_file.objects.items) |index| {160 for (elf_file.objects.items) |index| {
154 pruneInFile(elf_file.file(index).?, elf_file);161 pruneInFile(elf_file.file(index).?);
155 }162 }
156}163}
157164
src/link/Elf/relocatable.zig+12-11
...@@ -233,8 +233,10 @@ fn parseArchiveStaticLibReportingFailure(elf_file: *Elf, path: Path) void {...@@ -233,8 +233,10 @@ fn parseArchiveStaticLibReportingFailure(elf_file: *Elf, path: Path) void {
233233
234fn parseObjectStaticLib(elf_file: *Elf, path: Path) Elf.ParseError!void {234fn parseObjectStaticLib(elf_file: *Elf, path: Path) Elf.ParseError!void {
235 const gpa = elf_file.base.comp.gpa;235 const gpa = elf_file.base.comp.gpa;
236 const file_handles = &elf_file.file_handles;
237
236 const handle = try path.root_dir.handle.openFile(path.sub_path, .{});238 const handle = try path.root_dir.handle.openFile(path.sub_path, .{});
237 const fh = try elf_file.addFileHandle(handle);239 const fh = try Elf.addFileHandle(gpa, file_handles, handle);
238240
239 const index: File.Index = @intCast(try elf_file.files.addOne(gpa));241 const index: File.Index = @intCast(try elf_file.files.addOne(gpa));
240 elf_file.files.set(index, .{ .object = .{242 elf_file.files.set(index, .{ .object = .{
...@@ -248,27 +250,26 @@ fn parseObjectStaticLib(elf_file: *Elf, path: Path) Elf.ParseError!void {...@@ -248,27 +250,26 @@ fn parseObjectStaticLib(elf_file: *Elf, path: Path) Elf.ParseError!void {
248 try elf_file.objects.append(gpa, index);250 try elf_file.objects.append(gpa, index);
249251
250 const object = elf_file.file(index).?.object;252 const object = elf_file.file(index).?.object;
251 try object.parseAr(elf_file);253 try object.parseAr(path, elf_file);
252}254}
253255
254fn parseArchiveStaticLib(elf_file: *Elf, path: Path) Elf.ParseError!void {256fn parseArchiveStaticLib(elf_file: *Elf, path: Path) Elf.ParseError!void {
255 const gpa = elf_file.base.comp.gpa;257 const gpa = elf_file.base.comp.gpa;
258 const diags = &elf_file.base.comp.link_diags;
259 const file_handles = &elf_file.file_handles;
260
256 const handle = try path.root_dir.handle.openFile(path.sub_path, .{});261 const handle = try path.root_dir.handle.openFile(path.sub_path, .{});
257 const fh = try elf_file.addFileHandle(handle);262 const fh = try Elf.addFileHandle(gpa, file_handles, handle);
258263
259 var archive = Archive{};264 var archive = try Archive.parse(gpa, diags, file_handles, path, fh);
260 defer archive.deinit(gpa);265 defer archive.deinit(gpa);
261 try archive.parse(elf_file, path, fh);
262
263 const objects = try archive.objects.toOwnedSlice(gpa);
264 defer gpa.free(objects);
265266
266 for (objects) |extracted| {267 for (archive.objects) |extracted| {
267 const index = @as(File.Index, @intCast(try elf_file.files.addOne(gpa)));268 const index: File.Index = @intCast(try elf_file.files.addOne(gpa));
268 elf_file.files.set(index, .{ .object = extracted });269 elf_file.files.set(index, .{ .object = extracted });
269 const object = &elf_file.files.items(.data)[index].object;270 const object = &elf_file.files.items(.data)[index].object;
270 object.index = index;271 object.index = index;
271 try object.parseAr(elf_file);272 try object.parseAr(path, elf_file);
272 try elf_file.objects.append(gpa, index);273 try elf_file.objects.append(gpa, index);
273 }274 }
274}275}