Skip to content

Commit 55bafe1

Browse files
committed
elf: move ownership of symbols into objects
1 parent 1445d7a commit 55bafe1

13 files changed

+1475
-1074
lines changed

src/Elf.zig

+252-492
Large diffs are not rendered by default.

src/Elf/Atom.zig

+80-69
Large diffs are not rendered by default.

src/Elf/InternalObject.zig

+399-43
Large diffs are not rendered by default.

src/Elf/Object.zig

+260-135
Large diffs are not rendered by default.

src/Elf/SharedObject.zig

+227-103
Large diffs are not rendered by default.

src/Elf/Symbol.zig

+38-35
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ file: File.Index = 0,
1111

1212
/// Atom containing this symbol if any.
1313
/// Use `getAtom` to get the pointer to the atom.
14-
atom_ref: Elf.Ref = .{},
14+
ref: Elf.Ref = .{},
1515

1616
/// Assigned output section index for this symbol.
1717
shndx: u32 = 0,
1818

1919
/// Index of the source symbol this symbol references.
20-
/// Use `getSourceSymbol` to pull the source symbol from the relevant file.
21-
sym_idx: Index = 0,
20+
/// Use `getElfSym` to pull the source symbol from the relevant file.
21+
esym_idx: Index = 0,
2222

2323
/// Index of the source version symbol this symbol references if any.
2424
/// If the symbol is unversioned it will have either VER_NDX_LOCAL or VER_NDX_GLOBAL.
@@ -31,12 +31,12 @@ extra: u32 = 0,
3131

3232
pub fn isAbs(symbol: Symbol, elf_file: *Elf) bool {
3333
const file = symbol.getFile(elf_file).?;
34-
if (file == .shared) return symbol.getSourceSymbol(elf_file).st_shndx == elf.SHN_ABS;
34+
if (file == .shared) return symbol.getElfSym(elf_file).st_shndx == elf.SHN_ABS;
3535
return !symbol.flags.import and symbol.getAtom(elf_file) == null and symbol.getMergeSubsection(elf_file) == null and symbol.shndx == 0 and file != .internal;
3636
}
3737

3838
pub fn isLocal(symbol: Symbol, elf_file: *Elf) bool {
39-
if (elf_file.options.relocatable) return symbol.getSourceSymbol(elf_file).st_bind() == elf.STB_LOCAL;
39+
if (elf_file.options.relocatable) return symbol.getElfSym(elf_file).st_bind() == elf.STB_LOCAL;
4040
return !(symbol.flags.import or symbol.flags.@"export");
4141
}
4242

@@ -46,39 +46,41 @@ pub inline fn isIFunc(symbol: Symbol, elf_file: *Elf) bool {
4646

4747
pub fn getType(symbol: Symbol, elf_file: *Elf) u4 {
4848
const file = symbol.getFile(elf_file).?;
49-
const s_sym = symbol.getSourceSymbol(elf_file);
49+
const s_sym = symbol.getElfSym(elf_file);
5050
if (s_sym.st_type() == elf.STT_GNU_IFUNC and file == .shared) return elf.STT_FUNC;
5151
return s_sym.st_type();
5252
}
5353

5454
pub fn getName(symbol: Symbol, elf_file: *Elf) [:0]const u8 {
55-
return elf_file.string_intern.getAssumeExists(symbol.name);
55+
return switch (symbol.getFile(elf_file).?) {
56+
inline else => |x| x.getString(symbol.name),
57+
};
5658
}
5759

5860
pub fn getAtom(symbol: Symbol, elf_file: *Elf) ?*Atom {
59-
return elf_file.getAtom(symbol.atom_ref);
61+
return elf_file.getAtom(symbol.ref);
6062
}
6163

6264
pub fn getMergeSubsection(symbol: Symbol, elf_file: *Elf) ?*MergeSubsection {
6365
if (!symbol.flags.merge_subsection) return null;
64-
const extra = symbol.getExtra(elf_file).?;
66+
const extra = symbol.getExtra(elf_file);
6567
return elf_file.getMergeSubsection(extra.subsection);
6668
}
6769

68-
pub inline fn getFile(symbol: Symbol, elf_file: *Elf) ?File {
70+
pub fn getFile(symbol: Symbol, elf_file: *Elf) ?File {
6971
return elf_file.getFile(symbol.file);
7072
}
7173

72-
pub fn getSourceSymbol(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym {
74+
pub fn getElfSym(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym {
7375
const file = symbol.getFile(elf_file).?;
7476
return switch (file) {
75-
inline else => |x| x.symtab.items[symbol.sym_idx],
77+
inline else => |x| x.symtab.items[symbol.esym_idx],
7678
};
7779
}
7880

7981
pub fn getSymbolRank(symbol: Symbol, elf_file: *Elf) u32 {
8082
const file = symbol.getFile(elf_file) orelse return std.math.maxInt(u32);
81-
const sym = symbol.getSourceSymbol(elf_file);
83+
const sym = symbol.getElfSym(elf_file);
8284
const in_archive = switch (file) {
8385
.object => |x| !x.alive,
8486
else => false,
@@ -116,7 +118,7 @@ pub fn getAddress(symbol: Symbol, opts: struct {
116118
if (mem.startsWith(u8, sym_name, "__EH_FRAME_BEGIN__") or
117119
mem.startsWith(u8, sym_name, "__EH_FRAME_LIST__") or
118120
mem.startsWith(u8, sym_name, ".eh_frame_seg") or
119-
symbol.getSourceSymbol(elf_file).st_type() == elf.STT_SECTION)
121+
symbol.getElfSym(elf_file).st_type() == elf.STT_SECTION)
120122
{
121123
return @intCast(sh_addr);
122124
}
@@ -143,36 +145,36 @@ pub fn getOutputSymtabIndex(symbol: Symbol, elf_file: *Elf) ?u32 {
143145
const symtab_ctx = switch (file) {
144146
inline else => |x| x.output_symtab_ctx,
145147
};
146-
const idx = symbol.getExtra(elf_file).?.symtab;
148+
const idx = symbol.getExtra(elf_file).symtab;
147149
return if (symbol.isLocal(elf_file)) idx + symtab_ctx.ilocal else idx + symtab_ctx.iglobal;
148150
}
149151

150152
pub fn getGotAddress(symbol: Symbol, elf_file: *Elf) i64 {
151153
if (!symbol.flags.got) return 0;
152-
const extra = symbol.getExtra(elf_file).?;
154+
const extra = symbol.getExtra(elf_file);
153155
const entry = elf_file.got.entries.items[extra.got];
154156
return entry.getAddress(elf_file);
155157
}
156158

157159
pub fn getPltGotAddress(symbol: Symbol, elf_file: *Elf) i64 {
158160
if (!(symbol.flags.plt and symbol.flags.got)) return 0;
159-
const extra = symbol.getExtra(elf_file).?;
161+
const extra = symbol.getExtra(elf_file);
160162
const shdr = elf_file.sections.items(.shdr)[elf_file.plt_got_sect_index.?];
161163
const cpu_arch = elf_file.options.cpu_arch.?;
162164
return @intCast(shdr.sh_addr + extra.plt_got * PltGotSection.entrySize(cpu_arch));
163165
}
164166

165167
pub fn getPltAddress(symbol: Symbol, elf_file: *Elf) i64 {
166168
if (!symbol.flags.plt) return 0;
167-
const extra = symbol.getExtra(elf_file).?;
169+
const extra = symbol.getExtra(elf_file);
168170
const shdr = elf_file.sections.items(.shdr)[elf_file.plt_sect_index.?];
169171
const cpu_arch = elf_file.options.cpu_arch.?;
170172
return @intCast(shdr.sh_addr + extra.plt * PltSection.entrySize(cpu_arch) + PltSection.preambleSize(cpu_arch));
171173
}
172174

173175
pub fn getGotPltAddress(symbol: Symbol, elf_file: *Elf) i64 {
174176
if (!symbol.flags.plt) return 0;
175-
const extra = symbol.getExtra(elf_file).?;
177+
const extra = symbol.getExtra(elf_file);
176178
const shdr = elf_file.sections.items(.shdr)[elf_file.got_plt_sect_index.?];
177179
return @intCast(shdr.sh_addr + extra.plt * 8 + GotPltSection.preamble_size);
178180
}
@@ -185,29 +187,29 @@ pub fn getCopyRelAddress(symbol: Symbol, elf_file: *Elf) i64 {
185187

186188
pub fn getTlsGdAddress(symbol: Symbol, elf_file: *Elf) i64 {
187189
if (!symbol.flags.tlsgd) return 0;
188-
const extra = symbol.getExtra(elf_file).?;
190+
const extra = symbol.getExtra(elf_file);
189191
const entry = elf_file.got.entries.items[extra.tlsgd];
190192
return entry.getAddress(elf_file);
191193
}
192194

193195
pub fn getGotTpAddress(symbol: Symbol, elf_file: *Elf) i64 {
194196
if (!symbol.flags.gottp) return 0;
195-
const extra = symbol.getExtra(elf_file).?;
197+
const extra = symbol.getExtra(elf_file);
196198
const entry = elf_file.got.entries.items[extra.gottp];
197199
return entry.getAddress(elf_file);
198200
}
199201

200202
pub fn getTlsDescAddress(symbol: Symbol, elf_file: *Elf) i64 {
201203
if (!symbol.flags.tlsdesc) return 0;
202-
const extra = symbol.getExtra(elf_file).?;
204+
const extra = symbol.getExtra(elf_file);
203205
const entry = elf_file.got.entries.items[extra.tlsdesc];
204206
return entry.getAddress(elf_file);
205207
}
206208

207209
pub fn getAlignment(symbol: Symbol, elf_file: *Elf) !u64 {
208210
const file = symbol.getFile(elf_file) orelse return 0;
209211
const shared = file.shared;
210-
const s_sym = symbol.getSourceSymbol(elf_file);
212+
const s_sym = symbol.getElfSym(elf_file);
211213
const shdr = shared.shdrs.items[s_sym.st_shndx];
212214
const alignment = @max(1, shdr.sh_addralign);
213215
return if (s_sym.st_value == 0)
@@ -229,11 +231,8 @@ const AddExtraOpts = struct {
229231
subsection: ?u32 = null,
230232
};
231233

232-
pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) !void {
233-
if (symbol.getExtra(elf_file) == null) {
234-
symbol.extra = try elf_file.addSymbolExtra(.{});
235-
}
236-
var extra = symbol.getExtra(elf_file).?;
234+
pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) void {
235+
var extra = symbol.getExtra(elf_file);
237236
inline for (@typeInfo(@TypeOf(opts)).@"struct".fields) |field| {
238237
if (@field(opts, field.name)) |x| {
239238
@field(extra, field.name) = x;
@@ -242,17 +241,21 @@ pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) !void {
242241
symbol.setExtra(extra, elf_file);
243242
}
244243

245-
pub inline fn getExtra(symbol: Symbol, elf_file: *Elf) ?Extra {
246-
return elf_file.getSymbolExtra(symbol.extra);
244+
pub fn getExtra(symbol: Symbol, elf_file: *Elf) Extra {
245+
return switch (symbol.getFile(elf_file).?) {
246+
inline else => |x| x.getSymbolExtra(symbol.extra),
247+
};
247248
}
248249

249-
pub inline fn setExtra(symbol: Symbol, extra: Extra, elf_file: *Elf) void {
250-
elf_file.setSymbolExtra(symbol.extra, extra);
250+
pub fn setExtra(symbol: Symbol, extra: Extra, elf_file: *Elf) void {
251+
return switch (symbol.getFile(elf_file).?) {
252+
inline else => |x| x.setSymbolExtra(symbol.extra, extra),
253+
};
251254
}
252255

253256
pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
254257
const file = symbol.getFile(elf_file).?;
255-
const s_sym = symbol.getSourceSymbol(elf_file);
258+
const s_sym = symbol.getElfSym(elf_file);
256259
const st_type = symbol.getType(elf_file);
257260
const st_bind: u8 = blk: {
258261
if (symbol.isLocal(elf_file)) break :blk 0;
@@ -347,10 +350,10 @@ fn format2(
347350
_ = options;
348351
_ = unused_fmt_string;
349352
const symbol = ctx.symbol;
350-
try writer.print("%{d} : {s} : @{x}", .{ symbol.sym_idx, symbol.fmtName(ctx.elf_file), symbol.getAddress(.{}, ctx.elf_file) });
353+
try writer.print("%{d} : {s} : @{x}", .{ symbol.esym_idx, symbol.fmtName(ctx.elf_file), symbol.getAddress(.{}, ctx.elf_file) });
351354
if (symbol.getFile(ctx.elf_file)) |file| {
352355
if (symbol.isAbs(ctx.elf_file)) {
353-
if (symbol.getSourceSymbol(ctx.elf_file).st_shndx == elf.SHN_UNDEF) {
356+
if (symbol.getElfSym(ctx.elf_file).st_shndx == elf.SHN_UNDEF) {
354357
try writer.writeAll(" : undef");
355358
} else {
356359
try writer.writeAll(" : absolute");

src/Elf/Thunk.zig

+15-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
value: i64 = 0,
22
out_shndx: u32 = 0,
3-
symbols: std.AutoArrayHashMapUnmanaged(Symbol.Index, void) = .{},
3+
symbols: std.AutoArrayHashMapUnmanaged(Elf.Ref, void) = .empty,
44
output_symtab_ctx: Elf.SymtabCtx = .{},
55

66
pub fn deinit(thunk: *Thunk, allocator: Allocator) void {
@@ -17,9 +17,9 @@ pub fn getAddress(thunk: Thunk, elf_file: *Elf) i64 {
1717
return @as(i64, @intCast(shdr.sh_addr)) + thunk.value;
1818
}
1919

20-
pub fn getTargetAddress(thunk: Thunk, sym_index: Symbol.Index, elf_file: *Elf) i64 {
20+
pub fn getTargetAddress(thunk: Thunk, ref: Elf.Ref, elf_file: *Elf) i64 {
2121
const cpu_arch = elf_file.options.cpu_arch.?;
22-
return thunk.getAddress(elf_file) + @as(i64, @intCast(thunk.symbols.getIndex(sym_index).? * trampolineSize(cpu_arch)));
22+
return thunk.getAddress(elf_file) + @as(i64, @intCast(thunk.symbols.getIndex(ref).? * trampolineSize(cpu_arch)));
2323
}
2424

2525
pub fn isReachable(atom: *const Atom, rel: elf.Elf64_Rela, elf_file: *Elf) bool {
@@ -52,8 +52,8 @@ pub fn calcSymtabSize(thunk: *Thunk, elf_file: *Elf) void {
5252
if (elf_file.options.strip_all) return;
5353

5454
thunk.output_symtab_ctx.nlocals = @as(u32, @intCast(thunk.symbols.keys().len));
55-
for (thunk.symbols.keys()) |sym_index| {
56-
const sym = elf_file.getSymbol(sym_index);
55+
for (thunk.symbols.keys()) |ref| {
56+
const sym = elf_file.getSymbol(ref).?;
5757
thunk.output_symtab_ctx.strsize += @as(u32, @intCast(sym.getName(elf_file).len + "$thunk".len + 1));
5858
}
5959
}
@@ -62,8 +62,8 @@ pub fn writeSymtab(thunk: Thunk, elf_file: *Elf) void {
6262
if (elf_file.options.strip_all) return;
6363
const cpu_arch = elf_file.options.cpu_arch.?;
6464

65-
for (thunk.symbols.keys(), thunk.output_symtab_ctx.ilocal..) |sym_index, ilocal| {
66-
const sym = elf_file.getSymbol(sym_index);
65+
for (thunk.symbols.keys(), thunk.output_symtab_ctx.ilocal..) |ref, ilocal| {
66+
const sym = elf_file.getSymbol(ref).?;
6767
const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
6868
elf_file.strtab.appendSliceAssumeCapacity(sym.getName(elf_file));
6969
elf_file.strtab.appendSliceAssumeCapacity("$thunk");
@@ -73,7 +73,7 @@ pub fn writeSymtab(thunk: Thunk, elf_file: *Elf) void {
7373
.st_info = elf.STT_FUNC,
7474
.st_other = 0,
7575
.st_shndx = @intCast(thunk.out_shndx),
76-
.st_value = @intCast(thunk.getTargetAddress(sym_index, elf_file)),
76+
.st_value = @intCast(thunk.getTargetAddress(ref, elf_file)),
7777
.st_size = trampolineSize(cpu_arch),
7878
};
7979
}
@@ -123,9 +123,9 @@ fn format2(
123123
const thunk = ctx.thunk;
124124
const elf_file = ctx.elf_file;
125125
try writer.print("@{x} : size({x})\n", .{ thunk.value, thunk.size(elf_file) });
126-
for (thunk.symbols.keys()) |index| {
127-
const sym = elf_file.getSymbol(index);
128-
try writer.print(" %{d} : {s} : @{x}\n", .{ index, sym.getName(elf_file), sym.value });
126+
for (thunk.symbols.keys()) |ref| {
127+
const sym = elf_file.getSymbol(ref).?;
128+
try writer.print(" {} : {s} : @{x}\n", .{ ref, sym.getName(elf_file), sym.value });
129129
}
130130
}
131131

@@ -136,7 +136,8 @@ const aarch64 = struct {
136136
const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
137137
if (r_type != .CALL26 and r_type != .JUMP26) return true;
138138
const object = atom.getObject(elf_file);
139-
const target = object.getSymbol(rel.r_sym(), elf_file);
139+
const target_ref = object.resolveSymbol(rel.r_sym(), elf_file);
140+
const target = elf_file.getSymbol(target_ref).?;
140141
if (target.flags.plt) return false;
141142
if (atom.out_shndx != target.shndx) return false;
142143
const target_atom = target.getAtom(elf_file).?;
@@ -148,8 +149,8 @@ const aarch64 = struct {
148149
}
149150

150151
fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void {
151-
for (thunk.symbols.keys(), 0..) |sym_index, i| {
152-
const sym = elf_file.getSymbol(sym_index);
152+
for (thunk.symbols.keys(), 0..) |ref, i| {
153+
const sym = elf_file.getSymbol(ref).?;
153154
const saddr = thunk.getAddress(elf_file) + @as(i64, @intCast(i * trampoline_size));
154155
const taddr = sym.getAddress(.{}, elf_file);
155156
const pages = try util.calcNumberOfPages(saddr, taddr);

src/Elf/eh_frame.zig

+11-8
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,8 @@ pub const Cie = struct {
152152
if (cie_rel.r_type() != other_rel.r_type()) return false;
153153
if (cie_rel.r_addend != other_rel.r_addend) return false;
154154

155-
const cie_sym = cie.getObject(elf_file).getSymbol(cie_rel.r_sym(), elf_file);
156-
const other_sym = other.getObject(elf_file).getSymbol(other_rel.r_sym(), elf_file);
155+
const cie_sym = cie.getObject(elf_file).symbols.items[cie_rel.r_sym()];
156+
const other_sym = other.getObject(elf_file).symbols.items[other_rel.r_sym()];
157157
if (!std.mem.eql(u8, std.mem.asBytes(&cie_sym), std.mem.asBytes(&other_sym))) return false;
158158
}
159159
return true;
@@ -361,7 +361,8 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
361361
const data = cie.getData(elf_file);
362362

363363
for (cie.getRelocs(elf_file)) |rel| {
364-
const sym = object.getSymbol(rel.r_sym(), elf_file);
364+
const sym_ref = object.resolveSymbol(rel.r_sym(), elf_file);
365+
const sym = elf_file.getSymbol(sym_ref).?;
365366
resolveReloc(cie, sym, rel, elf_file, data) catch |err| switch (err) {
366367
error.RelocError => has_reloc_errors = true,
367368
else => |e| return e,
@@ -388,7 +389,8 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
388389
);
389390

390391
for (fde.getRelocs(elf_file)) |rel| {
391-
const sym = object.getSymbol(rel.r_sym(), elf_file);
392+
const sym_ref = object.resolveSymbol(rel.r_sym(), elf_file);
393+
const sym = elf_file.getSymbol(sym_ref).?;
392394
resolveReloc(fde, sym, rel, elf_file, data) catch |err| switch (err) {
393395
error.RelocError => has_reloc_errors = true,
394396
else => |e| return e,
@@ -437,7 +439,7 @@ pub fn writeEhFrameRelocatable(elf_file: *Elf, writer: anytype) !void {
437439
}
438440
}
439441

440-
fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela) elf.Elf64_Rela {
442+
fn emitReloc(elf_file: *Elf, rec: anytype, sym: Symbol, rel: elf.Elf64_Rela) elf.Elf64_Rela {
441443
const tracy = trace(@src());
442444
defer tracy.end();
443445

@@ -483,7 +485,7 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {
483485
for (object.cies.items) |cie| {
484486
if (!cie.alive) continue;
485487
for (cie.getRelocs(elf_file)) |rel| {
486-
const sym = object.getSymbol(rel.r_sym(), elf_file);
488+
const sym = object.symbols.items[rel.r_sym()];
487489
const out_rel = emitReloc(elf_file, cie, sym, rel);
488490
try writer.writeStruct(out_rel);
489491
}
@@ -492,7 +494,7 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {
492494
for (object.fdes.items) |fde| {
493495
if (!fde.alive) continue;
494496
for (fde.getRelocs(elf_file)) |rel| {
495-
const sym = object.getSymbol(rel.r_sym(), elf_file);
497+
const sym = object.symbols.items[rel.r_sym()];
496498
const out_rel = emitReloc(elf_file, fde, sym, rel);
497499
try writer.writeStruct(out_rel);
498500
}
@@ -544,7 +546,8 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void {
544546
const relocs = fde.getRelocs(elf_file);
545547
assert(relocs.len > 0); // Should this be an error? Things are completely broken anyhow if this trips...
546548
const rel = relocs[0];
547-
const sym = object.getSymbol(rel.r_sym(), elf_file);
549+
const sym_ref = object.resolveSymbol(rel.r_sym(), elf_file);
550+
const sym = elf_file.getSymbol(sym_ref).?;
548551
const P = @as(i64, @intCast(fde.getAddress(elf_file)));
549552
const S = @as(i64, @intCast(sym.getAddress(.{}, elf_file)));
550553
const A = rel.r_addend;

0 commit comments

Comments
 (0)