Skip to content

Commit d15cdd4

Browse files
committed
elf: move ownership of atoms into objects
1 parent 6aba6f3 commit d15cdd4

11 files changed

+248
-213
lines changed

src/Elf.zig

+40-96
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ symbols_extra: std.ArrayListUnmanaged(u32) = .{},
6060
globals: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},
6161
/// This table will be populated after `scanRelocs` has run.
6262
/// Key is symbol index.
63-
undefs: std.AutoHashMapUnmanaged(Symbol.Index, std.ArrayListUnmanaged(Atom.Index)) = .{},
63+
undefs: std.AutoHashMapUnmanaged(Symbol.Index, std.ArrayListUnmanaged(Ref)) = .{},
6464

6565
string_intern: StringTable = .{},
6666

@@ -84,8 +84,6 @@ rela_dyn: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},
8484
rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},
8585
comdat_group_sections: std.ArrayListUnmanaged(ComdatGroupSection) = .{},
8686

87-
atoms: std.ArrayListUnmanaged(Atom) = .{},
88-
atoms_extra: std.ArrayListUnmanaged(u32) = .{},
8987
thunks: std.ArrayListUnmanaged(Thunk) = .{},
9088

9189
merge_sections: std.ArrayListUnmanaged(MergeSection) = .{},
@@ -139,8 +137,6 @@ pub fn deinit(self: *Elf) void {
139137
self.shstrtab.deinit(gpa);
140138
self.symtab.deinit(gpa);
141139
self.strtab.deinit(gpa);
142-
self.atoms.deinit(gpa);
143-
self.atoms_extra.deinit(gpa);
144140
for (self.thunks.items) |*thunk| {
145141
thunk.deinit(gpa);
146142
}
@@ -275,9 +271,6 @@ pub fn flush(self: *Elf) !void {
275271
try self.dynstrtab.buffer.append(gpa, 0);
276272
// Append null section.
277273
_ = try self.addSection(.{ .name = "" });
278-
// Append null atom.
279-
try self.atoms.append(gpa, .{});
280-
try self.atoms_extra.append(gpa, 0);
281274
// Append null symbols.
282275
try self.symtab.append(gpa, null_sym);
283276
try self.symbols.append(gpa, .{});
@@ -456,11 +449,11 @@ fn sortInitFini(self: *Elf) !void {
456449

457450
const Entry = struct {
458451
priority: i32,
459-
atom_index: Atom.Index,
452+
atom_ref: Elf.Ref,
460453

461454
pub fn lessThan(ctx: *Elf, lhs: @This(), rhs: @This()) bool {
462455
if (lhs.priority == rhs.priority) {
463-
return ctx.getAtom(lhs.atom_index).?.getPriority(ctx) < ctx.getAtom(rhs.atom_index).?.getPriority(ctx);
456+
return ctx.getAtom(lhs.atom_ref).?.getPriority(ctx) < ctx.getAtom(rhs.atom_ref).?.getPriority(ctx);
464457
}
465458
return lhs.priority < rhs.priority;
466459
}
@@ -490,8 +483,8 @@ fn sortInitFini(self: *Elf) !void {
490483
try entries.ensureTotalCapacityPrecise(atoms.items.len);
491484
defer entries.deinit();
492485

493-
for (atoms.items) |atom_index| {
494-
const atom = self.getAtom(atom_index).?;
486+
for (atoms.items) |ref| {
487+
const atom = self.getAtom(ref).?;
495488
const file = atom.getObject(self);
496489
const priority = blk: {
497490
if (is_ctor_dtor) {
@@ -504,23 +497,23 @@ fn sortInitFini(self: *Elf) !void {
504497
const priority = std.fmt.parseUnsigned(u16, it.first(), 10) catch default;
505498
break :blk priority;
506499
};
507-
entries.appendAssumeCapacity(.{ .priority = priority, .atom_index = atom_index });
500+
entries.appendAssumeCapacity(.{ .priority = priority, .atom_ref = ref });
508501
}
509502

510503
mem.sort(Entry, entries.items, self, Entry.lessThan);
511504

512505
atoms.clearRetainingCapacity();
513506
for (entries.items) |entry| {
514-
atoms.appendAssumeCapacity(entry.atom_index);
507+
atoms.appendAssumeCapacity(entry.atom_ref);
515508
}
516509
}
517510
}
518511

519512
fn initOutputSections(self: *Elf) !void {
520513
for (self.objects.items) |index| {
521514
const object = self.getFile(index).?.object;
522-
for (object.atoms.items) |atom_index| {
523-
const atom = self.getAtom(atom_index) orelse continue;
515+
for (object.atoms_indexes.items) |atom_index| {
516+
const atom = object.getAtom(atom_index) orelse continue;
524517
if (!atom.flags.alive) continue;
525518
atom.out_shndx = try object.initOutputSection(self, atom.getInputShdr(self));
526519
}
@@ -746,11 +739,14 @@ pub fn initShStrtab(self: *Elf) !void {
746739
pub fn addAtomsToSections(self: *Elf) !void {
747740
for (self.objects.items) |index| {
748741
const object = self.getFile(index).?.object;
749-
for (object.atoms.items) |atom_index| {
750-
const atom = self.getAtom(atom_index) orelse continue;
742+
for (object.atoms_indexes.items) |atom_index| {
743+
const atom = object.getAtom(atom_index) orelse continue;
751744
if (!atom.flags.alive) continue;
752745
const atoms = &self.sections.items(.atoms)[atom.out_shndx];
753-
try atoms.append(self.base.allocator, atom_index);
746+
try atoms.append(self.base.allocator, .{
747+
.index = atom_index,
748+
.file = index,
749+
});
754750
}
755751

756752
for (object.getLocals()) |local_index| {
@@ -835,8 +831,8 @@ fn calcSectionSizes(self: *Elf) !void {
835831
if (atoms.items.len == 0) continue;
836832
if (self.requiresThunks() and shdr.sh_flags & elf.SHF_EXECINSTR != 0) continue;
837833

838-
for (atoms.items) |atom_index| {
839-
const atom = self.getAtom(atom_index).?;
834+
for (atoms.items) |ref| {
835+
const atom = self.getAtom(ref).?;
840836
const alignment = try math.powi(u64, 2, atom.alignment);
841837
const offset = mem.alignForward(u64, shdr.sh_size, alignment);
842838
const padding = offset - shdr.sh_size;
@@ -1551,8 +1547,9 @@ pub fn sortSections(self: *Elf) !void {
15511547
}
15521548

15531549
for (self.objects.items) |index| {
1554-
for (self.getFile(index).?.object.atoms.items) |atom_index| {
1555-
const atom = self.getAtom(atom_index) orelse continue;
1550+
const object = self.getFile(index).?.object;
1551+
for (object.atoms_indexes.items) |atom_index| {
1552+
const atom = object.getAtom(atom_index) orelse continue;
15561553
if (!atom.flags.alive) continue;
15571554
atom.out_shndx = backlinks[atom.out_shndx];
15581555
}
@@ -2084,8 +2081,8 @@ fn markEhFrameAtomsDead(self: *Elf) void {
20842081
const file = self.getFile(index).?;
20852082
if (!file.isAlive()) continue;
20862083
const object = file.object;
2087-
for (object.atoms.items) |atom_index| {
2088-
const atom = self.getAtom(atom_index) orelse continue;
2084+
for (object.atoms_indexes.items) |atom_index| {
2085+
const atom = object.getAtom(atom_index) orelse continue;
20892086
const is_eh_frame = (self.options.cpu_arch.? == .x86_64 and atom.getInputShdr(self).sh_type == elf.SHT_X86_64_UNWIND) or
20902087
mem.eql(u8, atom.getName(self), ".eh_frame");
20912088
if (atom.flags.alive and is_eh_frame) atom.flags.alive = false;
@@ -2234,7 +2231,7 @@ fn claimUnresolved(self: *Elf) void {
22342231
};
22352232

22362233
global.value = 0;
2237-
global.atom = 0;
2234+
global.atom_ref = .{};
22382235
global.sym_idx = sym_idx;
22392236
global.file = object.index;
22402237
global.ver_idx = if (is_import) elf.VER_NDX_LOCAL else self.default_sym_version;
@@ -2403,12 +2400,12 @@ fn writeAtoms(self: *Elf) !void {
24032400

24042401
var stream = std.io.fixedBufferStream(buffer);
24052402

2406-
for (atoms.items) |atom_index| {
2407-
const atom = self.getAtom(atom_index).?;
2403+
for (atoms.items) |ref| {
2404+
const atom = self.getAtom(ref).?;
24082405
assert(atom.flags.alive);
24092406
const off: u64 = @intCast(atom.value);
2410-
log.debug("writing ATOM(%{d},'{s}') at offset 0x{x}", .{
2411-
atom_index,
2407+
log.debug("writing ATOM({},'{s}') at offset 0x{x}", .{
2408+
ref,
24122409
atom.getName(self),
24132410
shdr.sh_offset + off,
24142411
});
@@ -2733,63 +2730,6 @@ pub fn getFileHandle(self: Elf, index: File.HandleIndex) File.Handle {
27332730
return self.file_handles.items[index];
27342731
}
27352732

2736-
pub fn addAtom(self: *Elf) !Atom.Index {
2737-
const index = @as(u32, @intCast(self.atoms.items.len));
2738-
const atom = try self.atoms.addOne(self.base.allocator);
2739-
atom.* = .{};
2740-
return index;
2741-
}
2742-
2743-
pub fn getAtom(self: Elf, atom_index: Atom.Index) ?*Atom {
2744-
if (atom_index == 0) return null;
2745-
assert(atom_index < self.atoms.items.len);
2746-
return &self.atoms.items[atom_index];
2747-
}
2748-
2749-
pub fn addAtomExtra(self: *Elf, extra: Atom.Extra) !u32 {
2750-
const fields = @typeInfo(Atom.Extra).@"struct".fields;
2751-
try self.atoms_extra.ensureUnusedCapacity(self.base.allocator, fields.len);
2752-
return self.addAtomExtraAssumeCapacity(extra);
2753-
}
2754-
2755-
pub fn addAtomExtraAssumeCapacity(self: *Elf, extra: Atom.Extra) u32 {
2756-
const index = @as(u32, @intCast(self.atoms_extra.items.len));
2757-
const fields = @typeInfo(Atom.Extra).@"struct".fields;
2758-
inline for (fields) |field| {
2759-
self.atoms_extra.appendAssumeCapacity(switch (field.type) {
2760-
u32 => @field(extra, field.name),
2761-
else => @compileError("bad field type"),
2762-
});
2763-
}
2764-
return index;
2765-
}
2766-
2767-
pub fn getAtomExtra(self: *Elf, index: u32) ?Atom.Extra {
2768-
if (index == 0) return null;
2769-
const fields = @typeInfo(Atom.Extra).@"struct".fields;
2770-
var i: usize = index;
2771-
var result: Atom.Extra = undefined;
2772-
inline for (fields) |field| {
2773-
@field(result, field.name) = switch (field.type) {
2774-
u32 => self.atoms_extra.items[i],
2775-
else => @compileError("bad field type"),
2776-
};
2777-
i += 1;
2778-
}
2779-
return result;
2780-
}
2781-
2782-
pub fn setAtomExtra(self: *Elf, index: u32, extra: Atom.Extra) void {
2783-
assert(index > 0);
2784-
const fields = @typeInfo(Atom.Extra).@"struct".fields;
2785-
inline for (fields, 0..) |field, i| {
2786-
self.atoms_extra.items[index + i] = switch (field.type) {
2787-
u32 => @field(extra, field.name),
2788-
else => @compileError("bad field type"),
2789-
};
2790-
}
2791-
}
2792-
27932733
fn addThunk(self: *Elf) !Thunk.Index {
27942734
const index = @as(Thunk.Index, @intCast(self.thunks.items.len));
27952735
const thunk = try self.thunks.addOne(self.base.allocator);
@@ -2821,8 +2761,8 @@ fn createThunks(self: *Elf, shndx: u32) !void {
28212761
const atoms = slice.items(.atoms)[shndx].items;
28222762
assert(atoms.len > 0);
28232763

2824-
for (atoms) |atom_index| {
2825-
self.getAtom(atom_index).?.value = -1;
2764+
for (atoms) |ref| {
2765+
self.getAtom(ref).?.value = -1;
28262766
}
28272767

28282768
var i: usize = 0;
@@ -2834,8 +2774,8 @@ fn createThunks(self: *Elf, shndx: u32) !void {
28342774
i += 1;
28352775

28362776
while (i < atoms.len) : (i += 1) {
2837-
const atom_index = atoms[i];
2838-
const atom = self.getAtom(atom_index).?;
2777+
const ref = atoms[i];
2778+
const atom = self.getAtom(ref).?;
28392779
assert(atom.flags.alive);
28402780
const alignment = try math.powi(u32, 2, atom.alignment);
28412781
if (@as(i64, @intCast(mem.alignForward(u64, shdr.sh_size, alignment))) - start_atom.value >= Thunk.maxAllowedDistance(cpu_arch)) break;
@@ -2848,16 +2788,16 @@ fn createThunks(self: *Elf, shndx: u32) !void {
28482788
thunk.out_shndx = shndx;
28492789

28502790
// Scan relocs in the group and create trampolines for any unreachable callsite
2851-
for (atoms[start..i]) |atom_index| {
2852-
const atom = self.getAtom(atom_index).?;
2791+
for (atoms[start..i]) |ref| {
2792+
const atom = self.getAtom(ref).?;
28532793
const object = atom.getObject(self);
2854-
log.debug("atom({d}) {s}", .{ atom_index, atom.getName(self) });
2794+
log.debug("atom({}) {s}", .{ ref, atom.getName(self) });
28552795
for (atom.getRelocs(self)) |rel| {
28562796
if (Thunk.isReachable(atom, rel, self)) continue;
28572797
const target = object.symbols.items[rel.r_sym()];
28582798
try thunk.symbols.put(gpa, target, {});
28592799
}
2860-
try atom.addExtra(.{ .thunk = thunk_index }, self);
2800+
atom.addExtra(.{ .thunk = thunk_index }, self);
28612801
atom.flags.thunk = true;
28622802
}
28632803

@@ -2995,6 +2935,10 @@ pub fn getMergeSection(self: *Elf, index: MergeSection.Index) *MergeSection {
29952935
return &self.merge_sections.items[index];
29962936
}
29972937

2938+
pub fn getAtom(self: *Elf, ref: Ref) ?*Atom {
2939+
return self.getFile(ref.file).?.getAtom(ref.index);
2940+
}
2941+
29982942
pub fn getComdatGroup(self: *Elf, ref: Ref) *ComdatGroup {
29992943
return self.getFile(ref.file).?.getComdatGroup(ref.index);
30002944
}
@@ -3257,7 +3201,7 @@ pub const LinkObject = struct {
32573201

32583202
const Section = struct {
32593203
shdr: elf.Elf64_Shdr,
3260-
atoms: std.ArrayListUnmanaged(Atom.Index) = .{},
3204+
atoms: std.ArrayListUnmanaged(Ref) = .{},
32613205
rela_shndx: u32 = 0,
32623206
sym_index: u32 = 0,
32633207
};

src/Elf/Atom.zig

+17-16
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,14 @@ pub fn getPriority(self: Atom, elf_file: *Elf) u64 {
9999

100100
pub fn getRelocs(self: Atom, elf_file: *Elf) []const elf.Elf64_Rela {
101101
if (self.relocs_shndx == 0) return &[0]elf.Elf64_Rela{};
102-
const extra = self.getExtra(elf_file).?;
102+
const extra = self.getExtra(elf_file);
103103
const object = self.getObject(elf_file);
104104
return object.relocs.items[extra.rel_index..][0..extra.rel_count];
105105
}
106106

107107
pub fn getThunk(self: Atom, elf_file: *Elf) *Thunk {
108108
assert(self.flags.thunk);
109-
const extra = self.getExtra(elf_file).?;
109+
const extra = self.getExtra(elf_file);
110110
return elf_file.getThunk(extra.thunk);
111111
}
112112

@@ -118,25 +118,23 @@ const AddExtraOpts = struct {
118118
rel_count: ?u32 = null,
119119
};
120120

121-
pub fn addExtra(atom: *Atom, opts: AddExtraOpts, elf_file: *Elf) !void {
122-
if (atom.getExtra(elf_file) == null) {
123-
atom.extra = try elf_file.addAtomExtra(.{});
124-
}
125-
var extra = atom.getExtra(elf_file).?;
121+
pub fn addExtra(atom: *Atom, opts: AddExtraOpts, elf_file: *Elf) void {
122+
const object = atom.getObject(elf_file);
123+
var extras = object.getAtomExtra(atom.extra);
126124
inline for (@typeInfo(@TypeOf(opts)).@"struct".fields) |field| {
127125
if (@field(opts, field.name)) |x| {
128-
@field(extra, field.name) = x;
126+
@field(extras, field.name) = x;
129127
}
130128
}
131-
atom.setExtra(extra, elf_file);
129+
object.setAtomExtra(atom.extra, extras);
132130
}
133131

134-
pub inline fn getExtra(atom: Atom, elf_file: *Elf) ?Extra {
135-
return elf_file.getAtomExtra(atom.extra);
132+
pub fn getExtra(atom: Atom, elf_file: *Elf) Extra {
133+
return atom.getObject(elf_file).getAtomExtra(atom.extra);
136134
}
137135

138-
pub inline fn setExtra(atom: Atom, extra: Extra, elf_file: *Elf) void {
139-
elf_file.setAtomExtra(atom.extra, extra);
136+
pub fn setExtra(atom: Atom, extras: Extra, elf_file: *Elf) void {
137+
atom.getObject(elf_file).setAtomExtra(atom.extra, extras);
140138
}
141139

142140
pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.Elf64_Rela)) !void {
@@ -184,7 +182,7 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El
184182

185183
pub fn getFdes(self: Atom, elf_file: *Elf) []Fde {
186184
if (!self.flags.fde) return &[0]Fde{};
187-
const extra = self.getExtra(elf_file).?;
185+
const extra = self.getExtra(elf_file);
188186
const object = self.getObject(elf_file);
189187
return object.fdes.items[extra.fde_start..][0..extra.fde_count];
190188
}
@@ -444,7 +442,10 @@ fn reportUndefSymbol(self: Atom, rel: elf.Elf64_Rela, elf_file: *Elf) !bool {
444442
if (!gop.found_existing) {
445443
gop.value_ptr.* = .{};
446444
}
447-
try gop.value_ptr.append(gpa, self.atom_index);
445+
try gop.value_ptr.append(gpa, .{
446+
.index = self.atom_index,
447+
.file = self.file,
448+
});
448449
return true;
449450
}
450451

@@ -737,7 +738,7 @@ fn format2(
737738
});
738739
if (atom.flags.fde) {
739740
try writer.writeAll(" : fdes{ ");
740-
const extra = atom.getExtra(elf_file).?;
741+
const extra = atom.getExtra(elf_file);
741742
for (atom.getFdes(elf_file), extra.fde_start..) |fde, i| {
742743
try writer.print("{d}", .{i});
743744
if (!fde.alive) try writer.writeAll("([*])");

src/Elf/InternalObject.zig

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub fn resolveSymbols(self: *InternalObject, elf_file: *Elf) void {
3838
const global = elf_file.getSymbol(index);
3939
if (self.asFile().getSymbolRank(this_sym, false) < global.getSymbolRank(elf_file)) {
4040
global.value = 0;
41-
global.atom = 0;
41+
global.atom_ref = .{};
4242
global.file = self.index;
4343
global.sym_idx = sym_idx;
4444
global.ver_idx = elf_file.default_sym_version;

0 commit comments

Comments
 (0)