authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-09-26 12:24:37+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-10-09 12:27:30-07:00
log7fead5d6dd078beda041ef2f490fb50ffae4dc82
tree1ce11df56c7ffaaece83a4ce2171313cf31fbc43
parentce5a5c361b5b098c3b7d68f88136a9c91e7bec19

elf: track atoms within AtomList with array hash map


4 files changed, 34 insertions(+), 33 deletions(-)

src/link/Elf.zig+14-14
...@@ -3219,7 +3219,7 @@ fn sortInitFini(self: *Elf) !void {...@@ -3219,7 +3219,7 @@ fn sortInitFini(self: *Elf) !void {
32193219
3220 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, *atom_list| {3220 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, *atom_list| {
3221 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;3221 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
3222 if (atom_list.atoms.items.len == 0) continue;3222 if (atom_list.atoms.keys().len == 0) continue;
32233223
3224 var is_init_fini = false;3224 var is_init_fini = false;
3225 var is_ctor_dtor = false;3225 var is_ctor_dtor = false;
...@@ -3236,10 +3236,10 @@ fn sortInitFini(self: *Elf) !void {...@@ -3236,10 +3236,10 @@ fn sortInitFini(self: *Elf) !void {
3236 if (!is_init_fini and !is_ctor_dtor) continue;3236 if (!is_init_fini and !is_ctor_dtor) continue;
32373237
3238 var entries = std.ArrayList(Entry).init(gpa);3238 var entries = std.ArrayList(Entry).init(gpa);
3239 try entries.ensureTotalCapacityPrecise(atom_list.atoms.items.len);3239 try entries.ensureTotalCapacityPrecise(atom_list.atoms.keys().len);
3240 defer entries.deinit();3240 defer entries.deinit();
32413241
3242 for (atom_list.atoms.items) |ref| {3242 for (atom_list.atoms.keys()) |ref| {
3243 const atom_ptr = self.atom(ref).?;3243 const atom_ptr = self.atom(ref).?;
3244 const object = atom_ptr.file(self).?.object;3244 const object = atom_ptr.file(self).?.object;
3245 const priority = blk: {3245 const priority = blk: {
...@@ -3260,7 +3260,7 @@ fn sortInitFini(self: *Elf) !void {...@@ -3260,7 +3260,7 @@ fn sortInitFini(self: *Elf) !void {
32603260
3261 atom_list.atoms.clearRetainingCapacity();3261 atom_list.atoms.clearRetainingCapacity();
3262 for (entries.items) |entry| {3262 for (entries.items) |entry| {
3263 atom_list.atoms.appendAssumeCapacity(entry.atom_ref);3263 _ = atom_list.atoms.getOrPutAssumeCapacity(entry.atom_ref);
3264 }3264 }
3265 }3265 }
3266}3266}
...@@ -3506,7 +3506,7 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {...@@ -3506,7 +3506,7 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {
3506 const slice = self.sections.slice();3506 const slice = self.sections.slice();
3507 for (slice.items(.shdr), slice.items(.atom_list_2)) |*shdr, *atom_list| {3507 for (slice.items(.shdr), slice.items(.atom_list_2)) |*shdr, *atom_list| {
3508 atom_list.output_section_index = backlinks[atom_list.output_section_index];3508 atom_list.output_section_index = backlinks[atom_list.output_section_index];
3509 for (atom_list.atoms.items) |ref| {3509 for (atom_list.atoms.keys()) |ref| {
3510 self.atom(ref).?.output_section_index = atom_list.output_section_index;3510 self.atom(ref).?.output_section_index = atom_list.output_section_index;
3511 }3511 }
3512 if (shdr.sh_type == elf.SHT_RELA) {3512 if (shdr.sh_type == elf.SHT_RELA) {
...@@ -3585,7 +3585,7 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {...@@ -3585,7 +3585,7 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {
3585fn updateSectionSizes(self: *Elf) !void {3585fn updateSectionSizes(self: *Elf) !void {
3586 const slice = self.sections.slice();3586 const slice = self.sections.slice();
3587 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, *atom_list| {3587 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, *atom_list| {
3588 if (atom_list.atoms.items.len == 0) continue;3588 if (atom_list.atoms.keys().len == 0) continue;
3589 if (self.requiresThunks() and shdr.sh_flags & elf.SHF_EXECINSTR != 0) continue;3589 if (self.requiresThunks() and shdr.sh_flags & elf.SHF_EXECINSTR != 0) continue;
3590 atom_list.updateSize(self);3590 atom_list.updateSize(self);
3591 try atom_list.allocate(self);3591 try atom_list.allocate(self);
...@@ -3594,7 +3594,7 @@ fn updateSectionSizes(self: *Elf) !void {...@@ -3594,7 +3594,7 @@ fn updateSectionSizes(self: *Elf) !void {
3594 if (self.requiresThunks()) {3594 if (self.requiresThunks()) {
3595 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, *atom_list| {3595 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, *atom_list| {
3596 if (shdr.sh_flags & elf.SHF_EXECINSTR == 0) continue;3596 if (shdr.sh_flags & elf.SHF_EXECINSTR == 0) continue;
3597 if (atom_list.atoms.items.len == 0) continue;3597 if (atom_list.atoms.keys().len == 0) continue;
35983598
3599 // Create jump/branch range extenders if needed.3599 // Create jump/branch range extenders if needed.
3600 try self.createThunks(atom_list);3600 try self.createThunks(atom_list);
...@@ -4058,7 +4058,7 @@ fn writeAtoms(self: *Elf) !void {...@@ -4058,7 +4058,7 @@ fn writeAtoms(self: *Elf) !void {
4058 var has_reloc_errors = false;4058 var has_reloc_errors = false;
4059 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, atom_list| {4059 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, atom_list| {
4060 if (shdr.sh_type == elf.SHT_NOBITS) continue;4060 if (shdr.sh_type == elf.SHT_NOBITS) continue;
4061 if (atom_list.atoms.items.len == 0) continue;4061 if (atom_list.atoms.keys().len == 0) continue;
4062 atom_list.write(&buffer, &undefs, self) catch |err| switch (err) {4062 atom_list.write(&buffer, &undefs, self) catch |err| switch (err) {
4063 error.UnsupportedCpuArch => {4063 error.UnsupportedCpuArch => {
4064 try self.reportUnsupportedCpuArch();4064 try self.reportUnsupportedCpuArch();
...@@ -5732,20 +5732,20 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {...@@ -5732,20 +5732,20 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {
5732 }5732 }
5733 }.advance;5733 }.advance;
57345734
5735 for (atom_list.atoms.items) |ref| {5735 for (atom_list.atoms.keys()) |ref| {
5736 elf_file.atom(ref).?.value = -1;5736 elf_file.atom(ref).?.value = -1;
5737 }5737 }
57385738
5739 var i: usize = 0;5739 var i: usize = 0;
5740 while (i < atom_list.atoms.items.len) {5740 while (i < atom_list.atoms.keys().len) {
5741 const start = i;5741 const start = i;
5742 const start_atom = elf_file.atom(atom_list.atoms.items[start]).?;5742 const start_atom = elf_file.atom(atom_list.atoms.keys()[start]).?;
5743 assert(start_atom.alive);5743 assert(start_atom.alive);
5744 start_atom.value = try advance(atom_list, start_atom.size, start_atom.alignment);5744 start_atom.value = try advance(atom_list, start_atom.size, start_atom.alignment);
5745 i += 1;5745 i += 1;
57465746
5747 while (i < atom_list.atoms.items.len) : (i += 1) {5747 while (i < atom_list.atoms.keys().len) : (i += 1) {
5748 const atom_ptr = elf_file.atom(atom_list.atoms.items[i]).?;5748 const atom_ptr = elf_file.atom(atom_list.atoms.keys()[i]).?;
5749 assert(atom_ptr.alive);5749 assert(atom_ptr.alive);
5750 if (@as(i64, @intCast(atom_ptr.alignment.forward(atom_list.size))) - start_atom.value >= max_distance)5750 if (@as(i64, @intCast(atom_ptr.alignment.forward(atom_list.size))) - start_atom.value >= max_distance)
5751 break;5751 break;
...@@ -5758,7 +5758,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {...@@ -5758,7 +5758,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {
5758 thunk_ptr.output_section_index = atom_list.output_section_index;5758 thunk_ptr.output_section_index = atom_list.output_section_index;
57595759
5760 // Scan relocs in the group and create trampolines for any unreachable callsite5760 // Scan relocs in the group and create trampolines for any unreachable callsite
5761 for (atom_list.atoms.items[start..i]) |ref| {5761 for (atom_list.atoms.keys()[start..i]) |ref| {
5762 const atom_ptr = elf_file.atom(ref).?;5762 const atom_ptr = elf_file.atom(ref).?;
5763 const file_ptr = atom_ptr.file(elf_file).?;5763 const file_ptr = atom_ptr.file(elf_file).?;
5764 log.debug("atom({}) {s}", .{ ref, atom_ptr.name(elf_file) });5764 log.debug("atom({}) {s}", .{ ref, atom_ptr.name(elf_file) });
src/link/Elf/AtomList.zig+17-16
...@@ -2,7 +2,8 @@ value: i64 = 0,...@@ -2,7 +2,8 @@ value: i64 = 0,
2size: u64 = 0,2size: u64 = 0,
3alignment: Atom.Alignment = .@"1",3alignment: Atom.Alignment = .@"1",
4output_section_index: u32 = 0,4output_section_index: u32 = 0,
5atoms: std.ArrayListUnmanaged(Elf.Ref) = .empty,5// atoms: std.ArrayListUnmanaged(Elf.Ref) = .empty,
6atoms: std.AutoArrayHashMapUnmanaged(Elf.Ref, void) = .empty,
67
7pub fn deinit(list: *AtomList, allocator: Allocator) void {8pub fn deinit(list: *AtomList, allocator: Allocator) void {
8 list.atoms.deinit(allocator);9 list.atoms.deinit(allocator);
...@@ -22,7 +23,7 @@ pub fn updateSize(list: *AtomList, elf_file: *Elf) void {...@@ -22,7 +23,7 @@ pub fn updateSize(list: *AtomList, elf_file: *Elf) void {
22 // TODO perhaps a 'stale' flag would be better here?23 // TODO perhaps a 'stale' flag would be better here?
23 list.size = 0;24 list.size = 0;
24 list.alignment = .@"1";25 list.alignment = .@"1";
25 for (list.atoms.items) |ref| {26 for (list.atoms.keys()) |ref| {
26 const atom_ptr = elf_file.atom(ref).?;27 const atom_ptr = elf_file.atom(ref).?;
27 assert(atom_ptr.alive);28 assert(atom_ptr.alive);
28 const off = atom_ptr.alignment.forward(list.size);29 const off = atom_ptr.alignment.forward(list.size);
...@@ -56,13 +57,13 @@ pub fn allocate(list: *AtomList, elf_file: *Elf) !void {...@@ -56,13 +57,13 @@ pub fn allocate(list: *AtomList, elf_file: *Elf) !void {
56 // FIXME:JK this currently ignores Thunks as valid chunks.57 // FIXME:JK this currently ignores Thunks as valid chunks.
57 {58 {
58 var idx: usize = 0;59 var idx: usize = 0;
59 while (idx < list.atoms.items.len) : (idx += 1) {60 while (idx < list.atoms.keys().len) : (idx += 1) {
60 const curr_atom_ptr = elf_file.atom(list.atoms.items[idx]).?;61 const curr_atom_ptr = elf_file.atom(list.atoms.keys()[idx]).?;
61 if (idx > 0) {62 if (idx > 0) {
62 curr_atom_ptr.prev_atom_ref = list.atoms.items[idx - 1];63 curr_atom_ptr.prev_atom_ref = list.atoms.keys()[idx - 1];
63 }64 }
64 if (idx + 1 < list.atoms.items.len) {65 if (idx + 1 < list.atoms.keys().len) {
65 curr_atom_ptr.next_atom_ref = list.atoms.items[idx + 1];66 curr_atom_ptr.next_atom_ref = list.atoms.keys()[idx + 1];
66 }67 }
67 }68 }
68 }69 }
...@@ -74,7 +75,7 @@ pub fn allocate(list: *AtomList, elf_file: *Elf) !void {...@@ -74,7 +75,7 @@ pub fn allocate(list: *AtomList, elf_file: *Elf) !void {
74 }75 }
7576
76 // FIXME:JK if we had a link from Atom to parent AtomList we would not need to update Atom's value or osec index77 // FIXME:JK if we had a link from Atom to parent AtomList we would not need to update Atom's value or osec index
77 for (list.atoms.items) |ref| {78 for (list.atoms.keys()) |ref| {
78 const atom_ptr = elf_file.atom(ref).?;79 const atom_ptr = elf_file.atom(ref).?;
79 atom_ptr.output_section_index = list.output_section_index;80 atom_ptr.output_section_index = list.output_section_index;
80 atom_ptr.value += list.value;81 atom_ptr.value += list.value;
...@@ -92,7 +93,7 @@ pub fn write(list: AtomList, buffer: *std.ArrayList(u8), undefs: anytype, elf_fi...@@ -92,7 +93,7 @@ pub fn write(list: AtomList, buffer: *std.ArrayList(u8), undefs: anytype, elf_fi
92 try buffer.ensureUnusedCapacity(list_size);93 try buffer.ensureUnusedCapacity(list_size);
93 buffer.appendNTimesAssumeCapacity(0, list_size);94 buffer.appendNTimesAssumeCapacity(0, list_size);
9495
95 for (list.atoms.items) |ref| {96 for (list.atoms.keys()) |ref| {
96 const atom_ptr = elf_file.atom(ref).?;97 const atom_ptr = elf_file.atom(ref).?;
97 assert(atom_ptr.alive);98 assert(atom_ptr.alive);
9899
...@@ -128,7 +129,7 @@ pub fn writeRelocatable(list: AtomList, buffer: *std.ArrayList(u8), elf_file: *E...@@ -128,7 +129,7 @@ pub fn writeRelocatable(list: AtomList, buffer: *std.ArrayList(u8), elf_file: *E
128 try buffer.ensureUnusedCapacity(list_size);129 try buffer.ensureUnusedCapacity(list_size);
129 buffer.appendNTimesAssumeCapacity(0, list_size);130 buffer.appendNTimesAssumeCapacity(0, list_size);
130131
131 for (list.atoms.items) |ref| {132 for (list.atoms.keys()) |ref| {
132 const atom_ptr = elf_file.atom(ref).?;133 const atom_ptr = elf_file.atom(ref).?;
133 assert(atom_ptr.alive);134 assert(atom_ptr.alive);
134135
...@@ -149,13 +150,13 @@ pub fn writeRelocatable(list: AtomList, buffer: *std.ArrayList(u8), elf_file: *E...@@ -149,13 +150,13 @@ pub fn writeRelocatable(list: AtomList, buffer: *std.ArrayList(u8), elf_file: *E
149}150}
150151
151pub fn firstAtom(list: AtomList, elf_file: *Elf) *Atom {152pub fn firstAtom(list: AtomList, elf_file: *Elf) *Atom {
152 assert(list.atoms.items.len > 0);153 assert(list.atoms.keys().len > 0);
153 return elf_file.atom(list.atoms.items[0]).?;154 return elf_file.atom(list.atoms.keys()[0]).?;
154}155}
155156
156pub fn lastAtom(list: AtomList, elf_file: *Elf) *Atom {157pub fn lastAtom(list: AtomList, elf_file: *Elf) *Atom {
157 assert(list.atoms.items.len > 0);158 assert(list.atoms.keys().len > 0);
158 return elf_file.atom(list.atoms.items[list.atoms.items.len - 1]).?;159 return elf_file.atom(list.atoms.keys()[list.atoms.keys().len - 1]).?;
159}160}
160161
161pub fn format(162pub fn format(
...@@ -191,9 +192,9 @@ fn format2(...@@ -191,9 +192,9 @@ fn format2(
191 list.alignment.toByteUnits() orelse 0, list.size,192 list.alignment.toByteUnits() orelse 0, list.size,
192 });193 });
193 try writer.writeAll(" : atoms{ ");194 try writer.writeAll(" : atoms{ ");
194 for (list.atoms.items, 0..) |ref, i| {195 for (list.atoms.keys(), 0..) |ref, i| {
195 try writer.print("{}", .{ref});196 try writer.print("{}", .{ref});
196 if (i < list.atoms.items.len - 1) try writer.writeAll(", ");197 if (i < list.atoms.keys().len - 1) try writer.writeAll(", ");
197 }198 }
198 try writer.writeAll(" }");199 try writer.writeAll(" }");
199}200}
src/link/Elf/Object.zig+1-1
...@@ -915,7 +915,7 @@ pub fn initOutputSections(self: *Object, elf_file: *Elf) !void {...@@ -915,7 +915,7 @@ pub fn initOutputSections(self: *Object, elf_file: *Elf) !void {
915 });915 });
916 const atom_list = &elf_file.sections.items(.atom_list_2)[osec];916 const atom_list = &elf_file.sections.items(.atom_list_2)[osec];
917 atom_list.output_section_index = osec;917 atom_list.output_section_index = osec;
918 try atom_list.atoms.append(elf_file.base.comp.gpa, atom_ptr.ref());918 _ = try atom_list.atoms.getOrPut(elf_file.base.comp.gpa, atom_ptr.ref());
919 }919 }
920}920}
921921
src/link/Elf/relocatable.zig+2-2
...@@ -335,7 +335,7 @@ fn initComdatGroups(elf_file: *Elf) !void {...@@ -335,7 +335,7 @@ fn initComdatGroups(elf_file: *Elf) !void {
335fn updateSectionSizes(elf_file: *Elf) !void {335fn updateSectionSizes(elf_file: *Elf) !void {
336 const slice = elf_file.sections.slice();336 const slice = elf_file.sections.slice();
337 for (slice.items(.atom_list_2)) |*atom_list| {337 for (slice.items(.atom_list_2)) |*atom_list| {
338 if (atom_list.atoms.items.len == 0) continue;338 if (atom_list.atoms.keys().len == 0) continue;
339 atom_list.updateSize(elf_file);339 atom_list.updateSize(elf_file);
340 try atom_list.allocate(elf_file);340 try atom_list.allocate(elf_file);
341 }341 }
...@@ -434,7 +434,7 @@ fn writeAtoms(elf_file: *Elf) !void {...@@ -434,7 +434,7 @@ fn writeAtoms(elf_file: *Elf) !void {
434 const slice = elf_file.sections.slice();434 const slice = elf_file.sections.slice();
435 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, atom_list| {435 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, atom_list| {
436 if (shdr.sh_type == elf.SHT_NOBITS) continue;436 if (shdr.sh_type == elf.SHT_NOBITS) continue;
437 if (atom_list.atoms.items.len == 0) continue;437 if (atom_list.atoms.keys().len == 0) continue;
438 try atom_list.writeRelocatable(&buffer, elf_file);438 try atom_list.writeRelocatable(&buffer, elf_file);
439 }439 }
440}440}