authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-11-08 01:06:00-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-11-09 03:31:26-05:00
logb1d46339b5aa647df2b61ca19694c613aef89c21
tree0bc4016042c89972837664646d2bbe87152468a3
parent80c961159b56c117281a87bfe7acf853182fb427

Elf2: implement object relocs


1 files changed, 403 insertions(+), 215 deletions(-)

src/link/Elf2.zig+403-215
......@@ -3,6 +3,7 @@ options: link.File.OpenOptions,
33mf: MappedFile,
44ni: Node.Known,
55nodes: std.MultiArrayList(Node),
6shdrs: std.ArrayList(Section),
67phdrs: std.ArrayList(MappedFile.Node.Index),
78si: Symbol.Known,
89symtab: std.ArrayList(Symbol),
......@@ -163,9 +164,10 @@ pub const Node = union(enum) {
163164 }
164165};
165166
167pub const Section = struct { si: Symbol.Index, rela_si: Symbol.Index };
168
166169pub const StringTable = struct {
167170 map: std.HashMapUnmanaged(u32, void, StringTable.Context, std.hash_map.default_max_load_percentage),
168 size: u32,
169171
170172 const Context = struct {
171173 slice: []const u8,
......@@ -193,14 +195,10 @@ pub const StringTable = struct {
193195 }
194196 };
195197
196 pub fn get(
197 st: *StringTable,
198 gpa: std.mem.Allocator,
199 mf: *MappedFile,
200 ni: MappedFile.Node.Index,
201 key: []const u8,
202 ) !u32 {
203 const slice_const = ni.sliceConst(mf);
198 pub fn get(st: *StringTable, elf: *Elf, si: Symbol.Index, key: []const u8) !u32 {
199 const gpa = elf.base.comp.gpa;
200 const ni = si.node(elf);
201 const slice_const = ni.sliceConst(&elf.mf);
204202 const gop = try st.map.getOrPutContextAdapted(
205203 gpa,
206204 key,
......@@ -208,11 +206,18 @@ pub const StringTable = struct {
208206 .{ .slice = slice_const },
209207 );
210208 if (gop.found_existing) return gop.key_ptr.*;
211 const old_size = st.size;
212 const new_size: u32 = @intCast(old_size + key.len + 1);
213 st.size = new_size;
214 try ni.resize(mf, gpa, new_size);
215 const slice = ni.slice(mf)[old_size..];
209 const old_size, const new_size = size: switch (elf.shdrPtr(si.shndx(elf))) {
210 inline else => |shdr| {
211 const old_size: u32 = @intCast(elf.targetLoad(&shdr.size));
212 const new_size: u32 = @intCast(old_size + key.len + 1);
213 elf.targetStore(&shdr.size, new_size);
214 break :size .{ old_size, new_size };
215 },
216 };
217 _, const node_size = ni.location(&elf.mf).resolve(&elf.mf);
218 if (new_size > node_size)
219 try ni.resize(&elf.mf, gpa, new_size +| new_size / MappedFile.growth_factor);
220 const slice = ni.slice(&elf.mf)[old_size..];
216221 @memcpy(slice[0..key.len], key);
217222 slice[key.len] = 0;
218223 gop.key_ptr.* = old_size;
......@@ -226,7 +231,7 @@ pub const Symbol = struct {
226231 loc_relocs: Reloc.Index,
227232 /// Relocations targeting this symbol
228233 target_relocs: Reloc.Index,
229 unused: u32 = 0,
234 unused: u32,
230235
231236 pub const Index = enum(u32) {
232237 null,
......@@ -252,6 +257,52 @@ pub const Symbol = struct {
252257 return @enumFromInt(@intFromEnum(si) + 1);
253258 }
254259
260 pub const Shndx = enum(Tag) {
261 UNDEF = std.elf.SHN_UNDEF,
262 LIVEPATCH = reserve(std.elf.SHN_LIVEPATCH),
263 ABS = reserve(std.elf.SHN_ABS),
264 COMMON = reserve(std.elf.SHN_COMMON),
265 _,
266
267 pub const Tag = u32;
268
269 pub const LORESERVE: Shndx = .fromSection(std.elf.SHN_LORESERVE);
270 pub const HIRESERVE: Shndx = .fromSection(std.elf.SHN_HIRESERVE);
271 comptime {
272 assert(@intFromEnum(HIRESERVE) == std.math.maxInt(Tag));
273 }
274
275 fn reserve(sec: std.elf.Section) Tag {
276 assert(sec >= std.elf.SHN_LORESERVE and sec <= std.elf.SHN_HIRESERVE);
277 return @as(Tag, std.math.maxInt(Tag) - std.elf.SHN_HIRESERVE) + sec;
278 }
279
280 pub fn fromSection(sec: std.elf.Section) Shndx {
281 return switch (sec) {
282 std.elf.SHN_UNDEF...std.elf.SHN_LORESERVE - 1 => @enumFromInt(sec),
283 std.elf.SHN_LORESERVE...std.elf.SHN_HIRESERVE => @enumFromInt(reserve(sec)),
284 };
285 }
286 pub fn toSection(s: Shndx) ?std.elf.Section {
287 return switch (@intFromEnum(s)) {
288 std.elf.SHN_UNDEF...std.elf.SHN_LORESERVE - 1 => |sec| @intCast(sec),
289 std.elf.SHN_LORESERVE...reserve(std.elf.SHN_LORESERVE) - 1 => null,
290 reserve(std.elf.SHN_LORESERVE)...reserve(std.elf.SHN_HIRESERVE) => |sec| @intCast(
291 sec - reserve(std.elf.SHN_LORESERVE) + std.elf.SHN_LORESERVE,
292 ),
293 };
294 }
295
296 pub fn get(s: Shndx, elf: *Elf) *Section {
297 return &elf.shdrs.items[@intFromEnum(s)];
298 }
299 };
300 pub fn shndx(si: Symbol.Index, elf: *Elf) Shndx {
301 return .fromSection(switch (elf.symPtr(si)) {
302 inline else => |sym| elf.targetLoad(&sym.shndx),
303 });
304 }
305
255306 pub const InitOptions = struct {
256307 name: []const u8 = "",
257308 lib_name: ?[]const u8 = null,
......@@ -260,48 +311,83 @@ pub const Symbol = struct {
260311 type: std.elf.STT,
261312 bind: std.elf.STB = .LOCAL,
262313 visibility: std.elf.STV = .DEFAULT,
263 shndx: std.elf.Section = std.elf.SHN_UNDEF,
314 shndx: Shndx = .UNDEF,
264315 };
265316 pub fn init(si: Symbol.Index, elf: *Elf, opts: InitOptions) !void {
266317 const gpa = elf.base.comp.gpa;
267318 const target_endian = elf.targetEndian();
268 const sym_size: usize = switch (elf.identClass()) {
269 .NONE, _ => unreachable,
270 inline else => |class| @sizeOf(class.ElfN().Sym),
271 };
272319 const name_strtab_entry = try elf.string(.strtab, opts.name);
273 try elf.si.symtab.node(elf).resize(&elf.mf, gpa, sym_size * elf.symtab.items.len);
320 switch (elf.shdrPtr(elf.si.symtab.shndx(elf))) {
321 inline else => |shdr| {
322 const old_size = elf.targetLoad(&shdr.size);
323 const ent_size = elf.targetLoad(&shdr.entsize);
324 const new_size = ent_size * elf.symtab.items.len;
325 if (new_size > old_size) {
326 elf.targetStore(&shdr.size, @intCast(new_size));
327 const symtab_ni = elf.si.symtab.node(elf);
328 _, const node_size = symtab_ni.location(&elf.mf).resolve(&elf.mf);
329 if (new_size > node_size) try symtab_ni.resize(
330 &elf.mf,
331 gpa,
332 new_size +| new_size / MappedFile.growth_factor,
333 );
334 }
335 },
336 }
274337 switch (elf.symPtr(si)) {
275338 inline else => |sym, class| {
339 const Sym = class.ElfN().Sym;
276340 sym.* = .{
277341 .name = name_strtab_entry,
278342 .value = @intCast(opts.value),
279343 .size = @intCast(opts.size),
280344 .info = .{ .type = opts.type, .bind = opts.bind },
281345 .other = .{ .visibility = opts.visibility },
282 .shndx = opts.shndx,
346 .shndx = opts.shndx.toSection().?,
283347 };
284 if (target_endian != native_endian) std.mem.byteSwapAllFields(class.ElfN().Sym, sym);
348 if (target_endian != native_endian) std.mem.byteSwapAllFields(Sym, sym);
285349 },
286350 }
351 switch (elf.shdrPtr(elf.si.symtab.shndx(elf))) {
352 inline else => |shdr| elf.targetStore(&shdr.info, @max(
353 elf.targetLoad(&shdr.info),
354 @intFromEnum(si) + 1,
355 )),
356 }
287357 if (opts.bind == .LOCAL or elf.si.dynsym == .null) return;
288358 const dsi = elf.dynsym.items.len;
289359 try elf.dynsym.append(gpa, si);
290 const dynsym_ni = elf.si.dynsym.node(elf);
291360 const name_dynstr_entry = try elf.string(.dynstr, opts.name);
292 try dynsym_ni.resize(&elf.mf, gpa, sym_size * elf.dynsym.items.len);
361 switch (elf.shdrPtr(elf.si.dynsym.shndx(elf))) {
362 inline else => |shdr| {
363 const old_size = elf.targetLoad(&shdr.size);
364 const ent_size = elf.targetLoad(&shdr.entsize);
365 const new_size = ent_size * elf.dynsym.items.len;
366 if (new_size > old_size) {
367 elf.targetStore(&shdr.size, @intCast(new_size));
368 const dynsym_ni = elf.si.dynsym.node(elf);
369 _, const node_size = dynsym_ni.location(&elf.mf).resolve(&elf.mf);
370 if (new_size > node_size) try dynsym_ni.resize(
371 &elf.mf,
372 gpa,
373 new_size +| new_size / MappedFile.growth_factor,
374 );
375 }
376 },
377 }
293378 switch (elf.dynsymSlice()) {
294 inline else => |dynsym, class| {
295 const dsym = &dynsym[dsi];
296 dsym.* = .{
379 inline else => |dynsyms, class| {
380 const Sym = class.ElfN().Sym;
381 const dynsym = &dynsyms[dsi];
382 dynsym.* = .{
297383 .name = name_dynstr_entry,
298384 .value = @intCast(opts.value),
299385 .size = @intCast(opts.size),
300386 .info = .{ .type = opts.type, .bind = opts.bind },
301387 .other = .{ .visibility = opts.visibility },
302 .shndx = opts.shndx,
388 .shndx = opts.shndx.toSection().?,
303389 };
304 if (target_endian != native_endian) std.mem.byteSwapAllFields(class.ElfN().Sym, dsym);
390 if (target_endian != native_endian) std.mem.byteSwapAllFields(Sym, dynsym);
305391 },
306392 }
307393 }
......@@ -321,6 +407,7 @@ pub const Symbol = struct {
321407 }
322408
323409 pub fn applyLocationRelocs(si: Symbol.Index, elf: *Elf) void {
410 if (elf.ehdrField(.type) == .REL) return;
324411 switch (si.get(elf).loc_relocs) {
325412 .none => {},
326413 else => |loc_relocs| for (elf.relocs.items[@intFromEnum(loc_relocs)..]) |*reloc| {
......@@ -331,6 +418,7 @@ pub const Symbol = struct {
331418 }
332419
333420 pub fn applyTargetRelocs(si: Symbol.Index, elf: *Elf) void {
421 if (elf.ehdrField(.type) == .REL) return;
334422 var ri = si.get(elf).target_relocs;
335423 while (ri != .none) {
336424 const reloc = ri.get(elf);
......@@ -374,7 +462,7 @@ pub const Reloc = extern struct {
374462 next: Reloc.Index,
375463 loc: Symbol.Index,
376464 target: Symbol.Index,
377 unused: u32,
465 rel_index: u32,
378466 offset: u64,
379467 addend: i64,
380468
......@@ -411,6 +499,7 @@ pub const Reloc = extern struct {
411499 };
412500
413501 pub fn apply(reloc: *const Reloc, elf: *Elf) void {
502 assert(elf.ehdrField(.type) != .REL);
414503 const loc_ni = reloc.loc.get(elf).ni;
415504 switch (loc_ni) {
416505 .none => return,
......@@ -601,6 +690,7 @@ fn create(
601690 .tls = .none,
602691 },
603692 .nodes = .empty,
693 .shdrs = .empty,
604694 .phdrs = .empty,
605695 .si = .{
606696 .dynsym = .null,
......@@ -611,16 +701,13 @@ fn create(
611701 .symtab = .empty,
612702 .shstrtab = .{
613703 .map = .empty,
614 .size = 1,
615704 },
616705 .strtab = .{
617706 .map = .empty,
618 .size = 1,
619707 },
620708 .dynsym = .empty,
621709 .dynstr = .{
622710 .map = .empty,
623 .size = 1,
624711 },
625712 .needed = .empty,
626713 .inputs = .empty,
......@@ -650,6 +737,7 @@ pub fn deinit(elf: *Elf) void {
650737 const gpa = elf.base.comp.gpa;
651738 elf.mf.deinit(gpa);
652739 elf.nodes.deinit(gpa);
740 elf.shdrs.deinit(gpa);
653741 elf.phdrs.deinit(gpa);
654742 elf.symtab.deinit(gpa);
655743 elf.shstrtab.map.deinit(gpa);
......@@ -681,11 +769,10 @@ fn initHeaders(
681769 const comp = elf.base.comp;
682770 const gpa = comp.gpa;
683771 const have_dynamic_section = switch (@"type") {
684 .NONE => unreachable,
772 .NONE, .CORE, _ => unreachable,
685773 .REL => false,
686774 .EXEC => comp.config.link_mode == .dynamic,
687775 .DYN => true,
688 .CORE, _ => unreachable,
689776 };
690777 const addr_align: std.mem.Alignment = switch (class) {
691778 .NONE, _ => unreachable,
......@@ -693,6 +780,7 @@ fn initHeaders(
693780 .@"64" => .@"8",
694781 };
695782
783 const shnum: u32 = 1;
696784 var phnum: u32 = 0;
697785 const phdr_phndx = phnum;
698786 phnum += 1;
......@@ -716,16 +804,16 @@ fn initHeaders(
716804 } else undefined;
717805
718806 const expected_nodes_len = expected_nodes_len: switch (@"type") {
719 .NONE => unreachable,
807 .NONE, .CORE, _ => unreachable,
720808 .REL => {
721809 defer phnum = 0;
722810 break :expected_nodes_len 5 + phnum;
723811 },
724812 .EXEC, .DYN => break :expected_nodes_len 5 + phnum * 2 +
725813 @as(usize, 2) * @intFromBool(have_dynamic_section),
726 .CORE, _ => unreachable,
727814 };
728815 try elf.nodes.ensureTotalCapacity(gpa, expected_nodes_len);
816 try elf.shdrs.ensureTotalCapacity(gpa, shnum);
729817 try elf.phdrs.resize(gpa, phnum);
730818 elf.nodes.appendAssumeCapacity(.file);
731819
......@@ -760,7 +848,7 @@ fn initHeaders(
760848 ehdr.phentsize = @sizeOf(ElfN.Phdr);
761849 ehdr.phnum = @min(phnum, std.elf.PN_XNUM);
762850 ehdr.shentsize = @sizeOf(ElfN.Shdr);
763 ehdr.shnum = 1;
851 ehdr.shnum = if (shnum < std.elf.SHN_LORESERVE) shnum else 0;
764852 ehdr.shstrndx = std.elf.SHN_UNDEF;
765853 if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(ElfN.Ehdr, ehdr);
766854 },
......@@ -768,7 +856,7 @@ fn initHeaders(
768856
769857 assert(elf.ni.shdr == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{
770858 .size = elf.ehdrField(.shentsize) * elf.ehdrField(.shnum),
771 .alignment = addr_align,
859 .alignment = elf.mf.flags.block_size,
772860 .moved = true,
773861 .resized = true,
774862 }));
......@@ -810,7 +898,8 @@ fn initHeaders(
810898 elf.phdrs.items[data_phndx] = elf.ni.data;
811899
812900 break :ph_vaddr switch (elf.ehdrField(.type)) {
813 else => 0,
901 .NONE, .CORE, _ => unreachable,
902 .REL, .DYN => 0,
814903 .EXEC => switch (elf.ehdrField(.machine)) {
815904 .@"386" => 0x400000,
816905 .AARCH64, .X86_64 => 0x200000,
......@@ -933,20 +1022,21 @@ fn initHeaders(
9331022 }
9341023 }
9351024
936 const sh_null: *ElfN.Shdr = @ptrCast(@alignCast(elf.ni.shdr.slice(&elf.mf)));
937 sh_null.* = .{
1025 const sh_undef: *ElfN.Shdr = @ptrCast(@alignCast(elf.ni.shdr.slice(&elf.mf)));
1026 sh_undef.* = .{
9381027 .name = try elf.string(.shstrtab, ""),
9391028 .type = .NULL,
9401029 .flags = .{ .shf = .{} },
9411030 .addr = 0,
9421031 .offset = 0,
943 .size = 0,
1032 .size = if (shnum < std.elf.SHN_LORESERVE) 0 else shnum,
9441033 .link = 0,
945 .info = if (phnum >= std.elf.PN_XNUM) phnum else 0,
1034 .info = if (phnum < std.elf.PN_XNUM) 0 else phnum,
9461035 .addralign = 0,
9471036 .entsize = 0,
9481037 };
949 if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Shdr, sh_null);
1038 if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Shdr, sh_undef);
1039 elf.shdrs.appendAssumeCapacity(.{ .si = .null, .rela_si = .null });
9501040
9511041 try elf.symtab.ensureTotalCapacity(gpa, 1);
9521042 elf.symtab.addOneAssumeCapacity().* = .{
......@@ -960,6 +1050,7 @@ fn initHeaders(
9601050 .size = @sizeOf(ElfN.Sym) * 1,
9611051 .addralign = addr_align,
9621052 .entsize = @sizeOf(ElfN.Sym),
1053 .node_align = elf.mf.flags.block_size,
9631054 }));
9641055 const symtab_null = @field(elf.symPtr(.null), @tagName(ct_class));
9651056 symtab_null.* = .{
......@@ -973,13 +1064,14 @@ fn initHeaders(
9731064 if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Sym, symtab_null);
9741065
9751066 const ehdr = @field(elf.ehdrPtr(), @tagName(ct_class));
976 ehdr.shstrndx = ehdr.shnum;
1067 elf.targetStore(&ehdr.shstrndx, ehdr.shnum);
9771068 },
9781069 }
9791070 assert(elf.si.shstrtab == try elf.addSection(elf.ni.file, .{
9801071 .type = .STRTAB,
981 .addralign = elf.mf.flags.block_size,
1072 .size = 1,
9821073 .entsize = 1,
1074 .node_align = elf.mf.flags.block_size,
9831075 }));
9841076 try elf.renameSection(.symtab, ".symtab");
9851077 try elf.renameSection(.shstrtab, ".shstrtab");
......@@ -989,96 +1081,100 @@ fn initHeaders(
9891081 .name = ".strtab",
9901082 .type = .STRTAB,
9911083 .size = 1,
992 .addralign = elf.mf.flags.block_size,
9931084 .entsize = 1,
1085 .node_align = elf.mf.flags.block_size,
9941086 }));
9951087 try elf.linkSections(.symtab, .strtab);
9961088 elf.si.strtab.node(elf).slice(&elf.mf)[0] = 0;
9971089
998 assert(elf.si.rodata == try elf.addSection(if (@"type" != .REL) elf.ni.rodata else elf.ni.file, .{
1090 assert(elf.si.rodata == try elf.addSection(elf.ni.rodata, .{
9991091 .name = ".rodata",
10001092 .flags = .{ .ALLOC = true },
10011093 .addralign = elf.mf.flags.block_size,
10021094 }));
1003 assert(elf.si.text == try elf.addSection(if (@"type" != .REL) elf.ni.text else elf.ni.file, .{
1095 assert(elf.si.text == try elf.addSection(elf.ni.text, .{
10041096 .name = ".text",
10051097 .flags = .{ .ALLOC = true, .EXECINSTR = true },
10061098 .addralign = elf.mf.flags.block_size,
10071099 }));
1008 assert(elf.si.data == try elf.addSection(if (@"type" != .REL) elf.ni.data else elf.ni.file, .{
1100 assert(elf.si.data == try elf.addSection(elf.ni.data, .{
10091101 .name = ".data",
10101102 .flags = .{ .WRITE = true, .ALLOC = true },
10111103 .addralign = elf.mf.flags.block_size,
10121104 }));
1013 if (maybe_interp) |interp| {
1014 const interp_ni = try elf.mf.addLastChildNode(gpa, elf.ni.rodata, .{
1015 .size = interp.len + 1,
1016 .moved = true,
1017 .resized = true,
1018 .bubbles_moved = false,
1019 });
1020 elf.nodes.appendAssumeCapacity(.{ .segment = interp_phndx });
1021 elf.phdrs.items[interp_phndx] = interp_ni;
1022
1023 const sec_interp_si = try elf.addSection(interp_ni, .{
1024 .type = .PROGBITS,
1025 .name = ".interp",
1026 .flags = .{ .ALLOC = true },
1027 .size = @intCast(interp.len + 1),
1028 });
1029 const sec_interp = sec_interp_si.node(elf).slice(&elf.mf);
1030 @memcpy(sec_interp[0..interp.len], interp);
1031 sec_interp[interp.len] = 0;
1032 }
1033 if (have_dynamic_section) {
1034 const dynamic_ni = try elf.mf.addLastChildNode(gpa, elf.ni.data, .{
1035 .moved = true,
1036 .bubbles_moved = false,
1037 });
1038 elf.nodes.appendAssumeCapacity(.{ .segment = dynamic_phndx });
1039 elf.phdrs.items[dynamic_phndx] = dynamic_ni;
1040
1041 switch (class) {
1042 .NONE, _ => unreachable,
1043 inline else => |ct_class| {
1044 const ElfN = ct_class.ElfN();
1045 elf.si.dynsym = try elf.addSection(elf.ni.rodata, .{
1046 .name = ".dynsym",
1047 .type = .DYNSYM,
1048 .size = @sizeOf(ElfN.Sym) * 1,
1049 .addralign = addr_align,
1050 .entsize = @sizeOf(ElfN.Sym),
1051 });
1052 const dynsym_null = &@field(elf.dynsymSlice(), @tagName(ct_class))[0];
1053 dynsym_null.* = .{
1054 .name = try elf.string(.dynstr, ""),
1055 .value = 0,
1056 .size = 0,
1057 .info = .{ .type = .NOTYPE, .bind = .LOCAL },
1058 .other = .{ .visibility = .DEFAULT },
1059 .shndx = std.elf.SHN_UNDEF,
1060 };
1061 if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(ElfN.Sym, dynsym_null);
1062 },
1105 if (@"type" != .REL) {
1106 if (maybe_interp) |interp| {
1107 const interp_ni = try elf.mf.addLastChildNode(gpa, elf.ni.rodata, .{
1108 .size = interp.len + 1,
1109 .moved = true,
1110 .resized = true,
1111 .bubbles_moved = false,
1112 });
1113 elf.nodes.appendAssumeCapacity(.{ .segment = interp_phndx });
1114 elf.phdrs.items[interp_phndx] = interp_ni;
1115
1116 const sec_interp_si = try elf.addSection(interp_ni, .{
1117 .type = .PROGBITS,
1118 .name = ".interp",
1119 .flags = .{ .ALLOC = true },
1120 .size = @intCast(interp.len + 1),
1121 });
1122 const sec_interp = sec_interp_si.node(elf).slice(&elf.mf);
1123 @memcpy(sec_interp[0..interp.len], interp);
1124 sec_interp[interp.len] = 0;
10631125 }
1064 elf.si.dynstr = try elf.addSection(elf.ni.rodata, .{
1065 .name = ".dynstr",
1066 .type = .STRTAB,
1067 .size = 1,
1068 .addralign = elf.mf.flags.block_size,
1069 .entsize = 1,
1070 });
1071 elf.si.dynamic = try elf.addSection(dynamic_ni, .{
1072 .name = ".dynamic",
1073 .type = .DYNAMIC,
1074 .flags = .{ .ALLOC = true, .WRITE = true },
1075 .addralign = addr_align,
1076 });
1077 try elf.linkSections(elf.si.dynamic, elf.si.dynstr);
1078 try elf.linkSections(elf.si.dynsym, elf.si.dynstr);
1079 }
1080 if (comp.config.any_non_single_threaded) {
1081 if (@"type" != .REL) {
1126 if (have_dynamic_section) {
1127 const dynamic_ni = try elf.mf.addLastChildNode(gpa, elf.ni.data, .{
1128 .moved = true,
1129 .bubbles_moved = false,
1130 });
1131 elf.nodes.appendAssumeCapacity(.{ .segment = dynamic_phndx });
1132 elf.phdrs.items[dynamic_phndx] = dynamic_ni;
1133
1134 switch (class) {
1135 .NONE, _ => unreachable,
1136 inline else => |ct_class| {
1137 const Sym = ct_class.ElfN().Sym;
1138 elf.si.dynsym = try elf.addSection(elf.ni.rodata, .{
1139 .name = ".dynsym",
1140 .type = .DYNSYM,
1141 .size = @sizeOf(Sym) * 1,
1142 .addralign = addr_align,
1143 .entsize = @sizeOf(Sym),
1144 .node_align = elf.mf.flags.block_size,
1145 });
1146 const dynsym_null = &@field(elf.dynsymSlice(), @tagName(ct_class))[0];
1147 dynsym_null.* = .{
1148 .name = try elf.string(.dynstr, ""),
1149 .value = 0,
1150 .size = 0,
1151 .info = .{ .type = .NOTYPE, .bind = .LOCAL },
1152 .other = .{ .visibility = .DEFAULT },
1153 .shndx = std.elf.SHN_UNDEF,
1154 };
1155 if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(
1156 Sym,
1157 dynsym_null,
1158 );
1159 },
1160 }
1161 elf.si.dynstr = try elf.addSection(elf.ni.rodata, .{
1162 .name = ".dynstr",
1163 .type = .STRTAB,
1164 .size = 1,
1165 .entsize = 1,
1166 .node_align = elf.mf.flags.block_size,
1167 });
1168 elf.si.dynamic = try elf.addSection(dynamic_ni, .{
1169 .name = ".dynamic",
1170 .type = .DYNAMIC,
1171 .flags = .{ .ALLOC = true, .WRITE = true },
1172 .node_align = addr_align,
1173 });
1174 try elf.linkSections(elf.si.dynamic, elf.si.dynstr);
1175 try elf.linkSections(elf.si.dynsym, elf.si.dynstr);
1176 }
1177 if (comp.config.any_non_single_threaded) {
10821178 elf.ni.tls = try elf.mf.addLastChildNode(gpa, elf.ni.rodata, .{
10831179 .alignment = elf.mf.flags.block_size,
10841180 .moved = true,
......@@ -1087,13 +1183,15 @@ fn initHeaders(
10871183 elf.nodes.appendAssumeCapacity(.{ .segment = tls_phndx });
10881184 elf.phdrs.items[tls_phndx] = elf.ni.tls;
10891185 }
1090
1091 elf.si.tdata = try elf.addSection(if (@"type" != .REL) elf.ni.tls else elf.ni.file, .{
1092 .name = ".tdata",
1093 .flags = .{ .WRITE = true, .ALLOC = true, .TLS = true },
1094 .addralign = elf.mf.flags.block_size,
1095 });
1186 } else {
1187 assert(maybe_interp == null);
1188 assert(!have_dynamic_section);
10961189 }
1190 if (comp.config.any_non_single_threaded) elf.si.tdata = try elf.addSection(elf.ni.tls, .{
1191 .name = ".tdata",
1192 .flags = .{ .WRITE = true, .ALLOC = true, .TLS = true },
1193 .addralign = elf.mf.flags.block_size,
1194 });
10971195 assert(elf.nodes.len == expected_nodes_len);
10981196}
10991197
......@@ -1218,6 +1316,7 @@ pub const PhdrSlice = union(std.elf.CLASS) {
12181316 @"64": []std.elf.Elf64.Phdr,
12191317};
12201318pub fn phdrSlice(elf: *Elf) PhdrSlice {
1319 assert(elf.ehdrField(.type) != .REL);
12211320 const slice = elf.ni.phdr.slice(&elf.mf);
12221321 return switch (elf.identClass()) {
12231322 .NONE, _ => unreachable,
......@@ -1246,6 +1345,17 @@ pub fn shdrSlice(elf: *Elf) ShdrSlice {
12461345 };
12471346}
12481347
1348pub const ShdrPtr = union(std.elf.CLASS) {
1349 NONE: noreturn,
1350 @"32": *std.elf.Elf32.Shdr,
1351 @"64": *std.elf.Elf64.Shdr,
1352};
1353pub fn shdrPtr(elf: *Elf, shndx: Symbol.Index.Shndx) ShdrPtr {
1354 return switch (elf.shdrSlice()) {
1355 inline else => |shdrs, class| @unionInit(ShdrPtr, @tagName(class), &shdrs[@intFromEnum(shndx)]),
1356 };
1357}
1358
12491359pub const SymtabSlice = union(std.elf.CLASS) {
12501360 NONE: noreturn,
12511361 @"32": []std.elf.Elf32.Sym,
......@@ -1258,7 +1368,11 @@ pub fn symtabSlice(elf: *Elf) SymtabSlice {
12581368 inline else => |class| @unionInit(
12591369 SymtabSlice,
12601370 @tagName(class),
1261 @ptrCast(@alignCast(slice)),
1371 @ptrCast(@alignCast(slice[0..std.mem.alignBackwardAnyAlign(
1372 usize,
1373 slice.len,
1374 @sizeOf(class.ElfN().Sym),
1375 )])),
12621376 ),
12631377 };
12641378}
......@@ -1270,7 +1384,7 @@ pub const SymPtr = union(std.elf.CLASS) {
12701384};
12711385pub fn symPtr(elf: *Elf, si: Symbol.Index) SymPtr {
12721386 return switch (elf.symtabSlice()) {
1273 inline else => |sym, class| @unionInit(SymPtr, @tagName(class), &sym[@intFromEnum(si)]),
1387 inline else => |syms, class| @unionInit(SymPtr, @tagName(class), &syms[@intFromEnum(si)]),
12741388 };
12751389}
12761390
......@@ -1560,7 +1674,7 @@ fn loadObject(
15601674 .si = try elf.initSymbolAssumeCapacity(.{
15611675 .name = std.fs.path.stem(member orelse path.sub_path),
15621676 .type = .FILE,
1563 .shndx = std.elf.SHN_ABS,
1677 .shndx = .ABS,
15641678 }),
15651679 };
15661680 const target_endian = elf.targetEndian();
......@@ -1626,7 +1740,7 @@ fn loadObject(
16261740 });
16271741 section.si = try elf.initSymbolAssumeCapacity(.{
16281742 .type = .SECTION,
1629 .shndx = elf.targetLoad(&@field(elf.symPtr(parent_si), @tagName(class)).shndx),
1743 .shndx = parent_si.shndx(elf),
16301744 });
16311745 section.si.get(elf).ni = ni;
16321746 elf.input_sections.addOneAssumeCapacity().* = .{
......@@ -1698,9 +1812,7 @@ fn loadObject(
16981812 .type = input_sym.info.type,
16991813 .bind = input_sym.info.bind,
17001814 .visibility = input_sym.other.visibility,
1701 .shndx = elf.targetLoad(switch (elf.symPtr(parent_si)) {
1702 inline else => |parent_sym| &parent_sym.shndx,
1703 }),
1815 .shndx = parent_si.shndx(elf),
17041816 });
17051817 si.get(elf).ni = parent_si.get(elf).ni;
17061818 switch (input_sym.info.bind) {
......@@ -1755,7 +1867,7 @@ fn loadObject(
17551867 "relocation section size (0x{x}) is not a multiple of entsize (0x{x})",
17561868 .{ rels.shdr.size, rels.shdr.entsize },
17571869 );
1758 try elf.relocs.ensureUnusedCapacity(gpa, relnum);
1870 try elf.ensureUnusedRelocCapacity(loc_sec.si, relnum);
17591871 try fr.seekTo(fl.offset + rels.shdr.offset);
17601872 for (0..relnum) |_| {
17611873 const rel = try r.peekStruct(Rel, target_endian);
......@@ -1832,13 +1944,13 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *std.Io.File.Reader) !void
18321944 var soname: ?ElfN.Addr = null;
18331945 try fr.seekTo(dynamic_ph.offset);
18341946 for (0..dynnum) |_| {
1835 const key = try r.takeInt(ElfN.Addr, target_endian);
1836 const value = try r.takeInt(ElfN.Addr, target_endian);
1837 switch (key) {
1947 const tag = try r.takeInt(ElfN.Addr, target_endian);
1948 const val = try r.takeInt(ElfN.Addr, target_endian);
1949 switch (tag) {
18381950 else => {},
1839 std.elf.DT_STRTAB => strtab = value,
1840 std.elf.DT_STRSZ => strsz = value,
1841 std.elf.DT_SONAME => soname = value,
1951 std.elf.DT_STRTAB => strtab = val,
1952 std.elf.DT_STRSZ => strsz = val,
1953 std.elf.DT_SONAME => soname = val,
18421954 }
18431955 }
18441956 if (strtab == null or soname == null)
......@@ -1883,11 +1995,7 @@ fn prelinkInner(elf: *Elf) !void {
18831995 std.fs.path.stem(elf.base.emit.sub_path),
18841996 });
18851997 defer gpa.free(zcu_name);
1886 const si = try elf.initSymbolAssumeCapacity(.{
1887 .name = zcu_name,
1888 .type = .FILE,
1889 .shndx = std.elf.SHN_ABS,
1890 });
1998 const si = try elf.initSymbolAssumeCapacity(.{ .name = zcu_name, .type = .FILE, .shndx = .ABS });
18911999 elf.inputs.addOneAssumeCapacity().* = .{
18922000 .path = elf.base.emit,
18932001 .member = null,
......@@ -1989,9 +2097,12 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
19892097 name: []const u8 = "",
19902098 type: std.elf.SHT = .NULL,
19912099 flags: std.elf.SHF = .{},
1992 size: std.elf.Word = 0,
2100 size: std.elf.Xword = 0,
2101 link: std.elf.Word = 0,
2102 info: std.elf.Word = 0,
19932103 addralign: std.mem.Alignment = .@"1",
19942104 entsize: std.elf.Word = 0,
2105 node_align: std.mem.Alignment = .@"1",
19952106}) !Symbol.Index {
19962107 switch (opts.type) {
19972108 .NULL => assert(opts.size == 0),
......@@ -2000,50 +2111,71 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
20002111 }
20012112 const gpa = elf.base.comp.gpa;
20022113 try elf.nodes.ensureUnusedCapacity(gpa, 1);
2114 try elf.shdrs.ensureUnusedCapacity(gpa, 1);
20032115 try elf.symtab.ensureUnusedCapacity(gpa, 1);
20042116
20052117 const shstrtab_entry = try elf.string(.shstrtab, opts.name);
2006 const shndx, const shdr_size = shndx: switch (elf.ehdrPtr()) {
2007 inline else => |ehdr| {
2008 const shndx = elf.targetLoad(&ehdr.shnum);
2009 const shnum = shndx + 1;
2010 elf.targetStore(&ehdr.shnum, shnum);
2011 break :shndx .{ shndx, elf.targetLoad(&ehdr.shentsize) * shnum };
2118 const shndx: Symbol.Index.Shndx, const new_shdr_size = shndx: switch (elf.ehdrPtr()) {
2119 inline else => |ehdr, class| {
2120 const shndx, const shnum = alloc_shndx: switch (elf.targetLoad(&ehdr.shnum)) {
2121 1...std.elf.SHN_LORESERVE - 2 => |shndx| {
2122 const shnum = shndx + 1;
2123 elf.targetStore(&ehdr.shnum, shnum);
2124 break :alloc_shndx .{ shndx, shnum };
2125 },
2126 std.elf.SHN_LORESERVE - 1 => |shndx| {
2127 const shnum = shndx + 1;
2128 elf.targetStore(&ehdr.shnum, 0);
2129 elf.targetStore(&@field(elf.shdrPtr(.UNDEF), @tagName(class)).size, shnum);
2130 break :alloc_shndx .{ shndx, shnum };
2131 },
2132 std.elf.SHN_LORESERVE...std.elf.SHN_HIRESERVE => unreachable,
2133 0 => {
2134 const shnum_ptr = &@field(elf.shdrPtr(.UNDEF), @tagName(class)).size;
2135 const shndx: u32 = @intCast(elf.targetLoad(shnum_ptr));
2136 const shnum = shndx + 1;
2137 elf.targetStore(shnum_ptr, shnum);
2138 break :alloc_shndx .{ shndx, shnum };
2139 },
2140 };
2141 assert(shndx < @intFromEnum(Symbol.Index.Shndx.LORESERVE));
2142 break :shndx .{ @enumFromInt(shndx), elf.targetLoad(&ehdr.shentsize) * shnum };
20122143 },
20132144 };
2014 try elf.ni.shdr.resize(&elf.mf, gpa, shdr_size);
2015 const ni = try elf.mf.addLastChildNode(gpa, segment_ni, .{
2016 .alignment = opts.addralign,
2145 _, const shdr_node_size = elf.ni.shdr.location(&elf.mf).resolve(&elf.mf);
2146 if (new_shdr_size > shdr_node_size)
2147 try elf.ni.shdr.resize(&elf.mf, gpa, new_shdr_size +| new_shdr_size / MappedFile.growth_factor);
2148 const ni = try elf.mf.addLastChildNode(gpa, switch (elf.ehdrField(.type)) {
2149 .NONE, .CORE, _ => unreachable,
2150 .REL => elf.ni.file,
2151 .EXEC, .DYN => segment_ni,
2152 }, .{
2153 .alignment = opts.addralign.max(opts.node_align),
20172154 .size = opts.size,
20182155 .resized = opts.size > 0,
20192156 });
20202157 const si = elf.addSymbolAssumeCapacity();
20212158 elf.nodes.appendAssumeCapacity(.{ .section = si });
2159 elf.shdrs.appendAssumeCapacity(.{ .si = si, .rela_si = .null });
20222160 si.get(elf).ni = ni;
20232161 const addr = elf.computeNodeVAddr(ni);
20242162 const offset = ni.fileLocation(&elf.mf, false).offset;
2025 try si.init(elf, .{
2026 .value = addr,
2027 .size = opts.size,
2028 .type = .SECTION,
2029 .shndx = shndx,
2030 });
2031 switch (elf.shdrSlice()) {
2032 inline else => |shdr| {
2033 const sh = &shdr[shndx];
2034 sh.* = .{
2163 try si.init(elf, .{ .value = addr, .type = .SECTION, .shndx = shndx });
2164 switch (elf.shdrPtr(shndx)) {
2165 inline else => |shdr, class| {
2166 shdr.* = .{
20352167 .name = shstrtab_entry,
20362168 .type = opts.type,
20372169 .flags = .{ .shf = opts.flags },
20382170 .addr = @intCast(addr),
20392171 .offset = @intCast(offset),
2040 .size = opts.size,
2041 .link = 0,
2042 .info = 0,
2172 .size = @intCast(opts.size),
2173 .link = opts.link,
2174 .info = opts.info,
20432175 .addralign = @intCast(opts.addralign.toByteUnits()),
20442176 .entsize = opts.entsize,
20452177 };
2046 if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(@TypeOf(sh.*), sh);
2178 if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(class.ElfN().Shdr, shdr);
20472179 },
20482180 }
20492181 return si;
......@@ -2051,39 +2183,27 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
20512183
20522184fn renameSection(elf: *Elf, si: Symbol.Index, name: []const u8) !void {
20532185 const shstrtab_entry = try elf.string(.shstrtab, name);
2054 switch (elf.shdrSlice()) {
2055 inline else => |shdr, class| elf.targetStore(
2056 &shdr[elf.targetLoad(&@field(elf.symPtr(si), @tagName(class)).shndx)].name,
2057 shstrtab_entry,
2058 ),
2186 switch (elf.shdrPtr(si.shndx(elf))) {
2187 inline else => |shdr| elf.targetStore(&shdr.name, shstrtab_entry),
20592188 }
20602189}
20612190
20622191fn linkSections(elf: *Elf, si: Symbol.Index, link_si: Symbol.Index) !void {
2063 switch (elf.shdrSlice()) {
2064 inline else => |shdr, class| shdr[
2065 elf.targetLoad(&@field(elf.symPtr(si), @tagName(class)).shndx)
2066 ].link = @field(elf.symPtr(link_si), @tagName(class)).shndx,
2192 switch (elf.shdrPtr(si.shndx(elf))) {
2193 inline else => |shdr| elf.targetStore(&shdr.link, @intFromEnum(link_si.shndx(elf))),
20672194 }
20682195}
20692196
20702197fn sectionName(elf: *Elf, si: Symbol.Index) [:0]const u8 {
2071 const name = elf.si.shstrtab.node(elf).slice(&elf.mf)[switch (elf.shdrSlice()) {
2072 inline else => |shndx, class| elf.targetLoad(
2073 &shndx[elf.targetLoad(&@field(elf.symPtr(si), @tagName(class)).shndx)].name,
2074 ),
2198 const name = elf.si.shstrtab.node(elf).slice(&elf.mf)[switch (elf.shdrPtr(si.shndx(elf))) {
2199 inline else => |shdr| elf.targetLoad(&shdr.name),
20752200 }..];
20762201 return name[0..std.mem.indexOfScalar(u8, name, 0).? :0];
20772202}
20782203
20792204fn string(elf: *Elf, comptime section: enum { shstrtab, strtab, dynstr }, key: []const u8) !u32 {
20802205 if (key.len == 0) return 0;
2081 return @field(elf, @tagName(section)).get(
2082 elf.base.comp.gpa,
2083 &elf.mf,
2084 @field(elf.si, @tagName(section)).node(elf),
2085 key,
2086 );
2206 return @field(elf, @tagName(section)).get(elf, @field(elf.si, @tagName(section)), key);
20872207}
20882208
20892209pub fn addReloc(
......@@ -2094,9 +2214,51 @@ pub fn addReloc(
20942214 addend: i64,
20952215 @"type": Reloc.Type,
20962216) !void {
2097 try elf.relocs.ensureUnusedCapacity(elf.base.comp.gpa, 1);
2217 try elf.ensureUnusedRelocCapacity(loc_si, 1);
20982218 elf.addRelocAssumeCapacity(loc_si, offset, target_si, addend, @"type");
20992219}
2220pub fn ensureUnusedRelocCapacity(elf: *Elf, loc_si: Symbol.Index, len: usize) !void {
2221 if (len == 0) return;
2222 const gpa = elf.base.comp.gpa;
2223
2224 try elf.relocs.ensureUnusedCapacity(gpa, len);
2225 if (elf.ehdrField(.type) != .REL) return;
2226
2227 const shndx = loc_si.shndx(elf);
2228 const sh = shndx.get(elf);
2229 if (sh.rela_si == .null) {
2230 var stack = std.heap.stackFallback(32, gpa);
2231 const allocator = stack.get();
2232
2233 const rela_name = try std.fmt.allocPrint(allocator, ".rela{s}", .{elf.sectionName(sh.si)});
2234 defer allocator.free(rela_name);
2235
2236 const class = elf.identClass();
2237 sh.rela_si = try elf.addSection(.none, .{
2238 .name = rela_name,
2239 .type = .RELA,
2240 .link = @intFromEnum(elf.si.symtab.shndx(elf)),
2241 .info = @intFromEnum(shndx),
2242 .addralign = switch (class) {
2243 .NONE, _ => unreachable,
2244 .@"32" => .@"4",
2245 .@"64" => .@"8",
2246 },
2247 .entsize = switch (class) {
2248 .NONE, _ => unreachable,
2249 inline else => |ct_class| @sizeOf(ct_class.ElfN().Rela),
2250 },
2251 .node_align = elf.mf.flags.block_size,
2252 });
2253 }
2254 const rela_ni = sh.rela_si.node(elf);
2255 _, const rela_node_size = rela_ni.location(&elf.mf).resolve(&elf.mf);
2256 const rela_size = switch (elf.shdrPtr(sh.rela_si.shndx(elf))) {
2257 inline else => |shdr| elf.targetLoad(&shdr.size) + elf.targetLoad(&shdr.entsize) * len,
2258 };
2259 if (rela_size > rela_node_size)
2260 try rela_ni.resize(&elf.mf, gpa, rela_size +| rela_size / MappedFile.growth_factor);
2261}
21002262pub fn addRelocAssumeCapacity(
21012263 elf: *Elf,
21022264 loc_si: Symbol.Index,
......@@ -2113,7 +2275,40 @@ pub fn addRelocAssumeCapacity(
21132275 .next = target.target_relocs,
21142276 .loc = loc_si,
21152277 .target = target_si,
2116 .unused = 0,
2278 .rel_index = switch (elf.ehdrField(.type)) {
2279 .NONE, .CORE, _ => unreachable,
2280 .REL => rel_index: {
2281 const rela_si = loc_si.shndx(elf).get(elf).rela_si;
2282 switch (elf.shdrPtr(rela_si.shndx(elf))) {
2283 inline else => |shdr, class| {
2284 const Rela = class.ElfN().Rela;
2285 const old_size = elf.targetLoad(&shdr.size);
2286 const ent_size = elf.targetLoad(&shdr.entsize);
2287 const new_size = old_size + ent_size;
2288 elf.targetStore(&shdr.size, @intCast(new_size));
2289 const rela: *Rela = @ptrCast(@alignCast(
2290 rela_si.node(elf).slice(&elf.mf)[@intCast(old_size)..@intCast(new_size)],
2291 ));
2292 rela.* = .{
2293 .offset = @intCast(offset),
2294 .info = .{
2295 .type = switch (elf.ehdrField(.machine)) {
2296 else => |machine| @panic(@tagName(machine)),
2297 inline .X86_64, .AARCH64, .RISCV, .PPC64 => |machine| @intCast(
2298 @intFromEnum(@field(@"type", @tagName(machine))),
2299 ),
2300 },
2301 .sym = @intCast(@intFromEnum(target_si)),
2302 },
2303 .addend = @intCast(addend),
2304 };
2305 if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(Rela, rela);
2306 break :rel_index @intCast(@divExact(old_size, ent_size));
2307 },
2308 }
2309 },
2310 .EXEC, .DYN => 0,
2311 },
21172312 .offset = offset,
21182313 .addend = addend,
21192314 };
......@@ -2479,7 +2674,8 @@ fn flushUav(
24792674 switch (sym.ni) {
24802675 .none => {
24812676 try elf.nodes.ensureUnusedCapacity(gpa, 1);
2482 const ni = try elf.mf.addLastChildNode(gpa, elf.si.data.node(elf), .{
2677 const sec_si = elf.si.data;
2678 const ni = try elf.mf.addLastChildNode(gpa, sec_si.node(elf), .{
24832679 .alignment = uav_align.toStdMem(),
24842680 .moved = true,
24852681 });
......@@ -2487,7 +2683,7 @@ fn flushUav(
24872683 sym.ni = ni;
24882684 switch (elf.symPtr(si)) {
24892685 inline else => |sym_ptr, class| sym_ptr.shndx =
2490 @field(elf.symPtr(.data), @tagName(class)).shndx,
2686 @field(elf.symPtr(sec_si), @tagName(class)).shndx,
24912687 }
24922688 },
24932689 else => {
......@@ -2611,11 +2807,10 @@ fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) !void {
26112807 var child_it = ni.children(&elf.mf);
26122808 while (child_it.next()) |child_ni| try elf.flushFileOffset(child_ni);
26132809 },
2614 .section => |si| switch (elf.shdrSlice()) {
2615 inline else => |shdr, class| elf.targetStore(
2616 &shdr[elf.targetLoad(&@field(elf.symPtr(si), @tagName(class)).shndx)].offset,
2617 @intCast(ni.fileLocation(&elf.mf, false).offset),
2618 ),
2810 .section => |si| switch (elf.shdrPtr(si.shndx(elf))) {
2811 inline else => |shdr| elf.targetStore(&shdr.offset, @intCast(
2812 ni.fileLocation(&elf.mf, false).offset,
2813 )),
26192814 },
26202815 }
26212816}
......@@ -2644,14 +2839,12 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void {
26442839 .section => |si| {
26452840 try elf.flushFileOffset(ni);
26462841 const addr = elf.computeNodeVAddr(ni);
2647 switch (elf.shdrSlice()) {
2842 switch (elf.shdrPtr(si.shndx(elf))) {
26482843 inline else => |shdr, class| {
2649 const sym = @field(elf.symPtr(si), @tagName(class));
2650 const sh = &shdr[elf.targetLoad(&sym.shndx)];
2651 const flags = elf.targetLoad(&sh.flags).shf;
2844 const flags = elf.targetLoad(&shdr.flags).shf;
26522845 if (flags.ALLOC) {
2653 elf.targetStore(&sh.addr, @intCast(addr));
2654 sym.value = sh.addr;
2846 elf.targetStore(&shdr.addr, @intCast(addr));
2847 @field(elf.symPtr(si), @tagName(class)).value = shdr.addr;
26552848 }
26562849 },
26572850 }
......@@ -2732,20 +2925,15 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void {
27322925 }
27332926 },
27342927 },
2735 .section => |si| switch (elf.symPtr(si)) {
2736 inline else => |sym, class| {
2737 const sh = &@field(elf.shdrSlice(), @tagName(class))[elf.targetLoad(&sym.shndx)];
2738 elf.targetStore(&sh.size, @intCast(size));
2739 switch (elf.targetLoad(&sh.type)) {
2928 .section => |si| switch (elf.shdrPtr(si.shndx(elf))) {
2929 inline else => |shdr| {
2930 switch (elf.targetLoad(&shdr.type)) {
27402931 else => unreachable,
2741 .NULL => if (size > 0) elf.targetStore(&sh.type, .PROGBITS),
2742 .PROGBITS => if (size == 0) elf.targetStore(&sh.type, .NULL),
2743 .SYMTAB, .DYNSYM => elf.targetStore(
2744 &sh.info,
2745 @intCast(@divExact(size, elf.targetLoad(&sh.entsize))),
2746 ),
2747 .STRTAB, .DYNAMIC => {},
2932 .NULL => if (size > 0) elf.targetStore(&shdr.type, .PROGBITS),
2933 .PROGBITS => if (size == 0) elf.targetStore(&shdr.type, .NULL),
2934 .SYMTAB, .STRTAB, .RELA, .DYNAMIC, .REL, .DYNSYM => return,
27482935 }
2936 elf.targetStore(&shdr.size, @intCast(size));
27492937 },
27502938 },
27512939 .input_section => {},