authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-09-04 11:40:56+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-09-04 13:34:26+02:00
logd302a1068effe4edcd36bd01f77ac2e1b1048e16
treebe0f2fc35bb60239b4fbb4e8ebdbe416ddca1f6e
parent64ad6eff16aac1f6154efa12406818efed57bf73

elf: rename SectionChunk into AtomList and store as part of Section


3 files changed, 103 insertions(+), 326 deletions(-)

src/link/Elf.zig+84-49
......@@ -393,7 +393,8 @@ pub fn deinit(self: *Elf) void {
393393 self.objects.deinit(gpa);
394394 self.shared_objects.deinit(gpa);
395395
396 for (self.sections.items(.atom_list), self.sections.items(.free_list)) |*atoms, *free_list| {
396 for (self.sections.items(.atom_list_2), self.sections.items(.atom_list), self.sections.items(.free_list)) |*atom_list, *atoms, *free_list| {
397 atom_list.deinit(gpa);
397398 atoms.deinit(gpa);
398399 free_list.deinit(gpa);
399400 }
......@@ -3204,8 +3205,9 @@ fn sortInitFini(self: *Elf) !void {
32043205 }
32053206 };
32063207
3207 for (slice.items(.shdr), slice.items(.atom_list)) |shdr, *atom_list| {
3208 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, *atom_list| {
32083209 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
3210 if (atom_list.atoms.items.len == 0) continue;
32093211
32103212 var is_init_fini = false;
32113213 var is_ctor_dtor = false;
......@@ -3219,15 +3221,13 @@ fn sortInitFini(self: *Elf) !void {
32193221 is_ctor_dtor = mem.indexOf(u8, name, ".ctors") != null or mem.indexOf(u8, name, ".dtors") != null;
32203222 },
32213223 }
3222
32233224 if (!is_init_fini and !is_ctor_dtor) continue;
3224 if (atom_list.items.len == 0) continue;
32253225
32263226 var entries = std.ArrayList(Entry).init(gpa);
3227 try entries.ensureTotalCapacityPrecise(atom_list.items.len);
3227 try entries.ensureTotalCapacityPrecise(atom_list.atoms.items.len);
32283228 defer entries.deinit();
32293229
3230 for (atom_list.items) |ref| {
3230 for (atom_list.atoms.items) |ref| {
32313231 const atom_ptr = self.atom(ref).?;
32323232 const object = atom_ptr.file(self).?.object;
32333233 const priority = blk: {
......@@ -3246,9 +3246,9 @@ fn sortInitFini(self: *Elf) !void {
32463246
32473247 mem.sort(Entry, entries.items, self, Entry.lessThan);
32483248
3249 atom_list.clearRetainingCapacity();
3249 atom_list.atoms.clearRetainingCapacity();
32503250 for (entries.items) |entry| {
3251 atom_list.appendAssumeCapacity(entry.atom_ref);
3251 atom_list.atoms.appendAssumeCapacity(entry.atom_ref);
32523252 }
32533253 }
32543254}
......@@ -3491,13 +3491,19 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {
34913491 msec.output_section_index = backlinks[msec.output_section_index];
34923492 }
34933493
3494 for (self.sections.items(.shdr)) |*shdr| {
3495 if (shdr.sh_type != elf.SHT_RELA) continue;
3496 // FIXME:JK we should spin up .symtab potentially earlier, or set all non-dynamic RELA sections
3497 // to point at symtab
3498 // shdr.sh_link = backlinks[shdr.sh_link];
3499 shdr.sh_link = self.symtab_section_index.?;
3500 shdr.sh_info = backlinks[shdr.sh_info];
3494 const slice = self.sections.slice();
3495 for (slice.items(.shdr), slice.items(.atom_list_2)) |*shdr, *atom_list| {
3496 atom_list.output_section_index = backlinks[atom_list.output_section_index];
3497 for (atom_list.atoms.items) |ref| {
3498 self.atom(ref).?.output_section_index = atom_list.output_section_index;
3499 }
3500 if (shdr.sh_type == elf.SHT_RELA) {
3501 // FIXME:JK we should spin up .symtab potentially earlier, or set all non-dynamic RELA sections
3502 // to point at symtab
3503 // shdr.sh_link = backlinks[shdr.sh_link];
3504 shdr.sh_link = self.symtab_section_index.?;
3505 shdr.sh_info = backlinks[shdr.sh_info];
3506 }
35013507 }
35023508
35033509 if (self.zigObjectPtr()) |zo| {
......@@ -3507,79 +3513,71 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {
35073513 }
35083514 }
35093515
3510 for (self.objects.items) |index| {
3511 const object = self.file(index).?.object;
3512 for (object.section_chunks.items) |*chunk| {
3513 chunk.output_section_index = backlinks[chunk.output_section_index];
3514 for (chunk.atoms.items) |atom_index| {
3515 object.atom(atom_index).?.output_section_index = chunk.output_section_index;
3516 }
3517 }
3518 }
3519
35203516 for (self.comdat_group_sections.items) |*cg| {
35213517 cg.shndx = backlinks[cg.shndx];
35223518 }
35233519
35243520 if (self.symtab_section_index) |index| {
3525 const shdr = &self.sections.items(.shdr)[index];
3521 const shdr = &slice.items(.shdr)[index];
35263522 shdr.sh_link = self.strtab_section_index.?;
35273523 }
35283524
35293525 if (self.dynamic_section_index) |index| {
3530 const shdr = &self.sections.items(.shdr)[index];
3526 const shdr = &slice.items(.shdr)[index];
35313527 shdr.sh_link = self.dynstrtab_section_index.?;
35323528 }
35333529
35343530 if (self.dynsymtab_section_index) |index| {
3535 const shdr = &self.sections.items(.shdr)[index];
3531 const shdr = &slice.items(.shdr)[index];
35363532 shdr.sh_link = self.dynstrtab_section_index.?;
35373533 }
35383534
35393535 if (self.hash_section_index) |index| {
3540 const shdr = &self.sections.items(.shdr)[index];
3536 const shdr = &slice.items(.shdr)[index];
35413537 shdr.sh_link = self.dynsymtab_section_index.?;
35423538 }
35433539
35443540 if (self.gnu_hash_section_index) |index| {
3545 const shdr = &self.sections.items(.shdr)[index];
3541 const shdr = &slice.items(.shdr)[index];
35463542 shdr.sh_link = self.dynsymtab_section_index.?;
35473543 }
35483544
35493545 if (self.versym_section_index) |index| {
3550 const shdr = &self.sections.items(.shdr)[index];
3546 const shdr = &slice.items(.shdr)[index];
35513547 shdr.sh_link = self.dynsymtab_section_index.?;
35523548 }
35533549
35543550 if (self.verneed_section_index) |index| {
3555 const shdr = &self.sections.items(.shdr)[index];
3551 const shdr = &slice.items(.shdr)[index];
35563552 shdr.sh_link = self.dynstrtab_section_index.?;
35573553 }
35583554
35593555 if (self.rela_dyn_section_index) |index| {
3560 const shdr = &self.sections.items(.shdr)[index];
3556 const shdr = &slice.items(.shdr)[index];
35613557 shdr.sh_link = self.dynsymtab_section_index orelse 0;
35623558 }
35633559
35643560 if (self.rela_plt_section_index) |index| {
3565 const shdr = &self.sections.items(.shdr)[index];
3561 const shdr = &slice.items(.shdr)[index];
35663562 shdr.sh_link = self.dynsymtab_section_index.?;
35673563 shdr.sh_info = self.plt_section_index.?;
35683564 }
35693565
35703566 if (self.eh_frame_rela_section_index) |index| {
3571 const shdr = &self.sections.items(.shdr)[index];
3567 const shdr = &slice.items(.shdr)[index];
35723568 shdr.sh_link = self.symtab_section_index.?;
35733569 shdr.sh_info = self.eh_frame_section_index.?;
35743570 }
35753571}
35763572
35773573fn updateSectionSizes(self: *Elf) !void {
3578 for (self.objects.items) |index| {
3579 try self.file(index).?.object.allocateAtoms(self);
3574 const slice = self.sections.slice();
3575 for (slice.items(.atom_list_2)) |*atom_list| {
3576 if (atom_list.atoms.items.len == 0) continue;
3577 atom_list.updateSize(self);
3578 try atom_list.allocate(self);
35803579 }
35813580
3582 const slice = self.sections.slice();
35833581 if (self.requiresThunks()) {
35843582 for (slice.items(.shdr), slice.items(.atom_list), 0..) |*shdr, atom_list, shndx| {
35853583 if (shdr.sh_flags & elf.SHF_EXECINSTR == 0) continue;
......@@ -4033,15 +4031,38 @@ fn allocateSpecialPhdrs(self: *Elf) void {
40334031}
40344032
40354033fn writeAtoms(self: *Elf) !void {
4036 for (self.objects.items) |index| {
4037 try self.file(index).?.object.writeAtoms(self);
4034 const gpa = self.base.comp.gpa;
4035
4036 var undefs = std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(Ref)).init(gpa);
4037 defer {
4038 for (undefs.values()) |*refs| {
4039 refs.deinit();
4040 }
4041 undefs.deinit();
40384042 }
40394043
4040 if (self.requiresThunks()) {
4041 const gpa = self.base.comp.gpa;
4042 var buffer = std.ArrayList(u8).init(gpa);
4043 defer buffer.deinit();
4044 var buffer = std.ArrayList(u8).init(gpa);
4045 defer buffer.deinit();
4046
4047 const slice = self.sections.slice();
4048 var has_reloc_errors = false;
4049 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, atom_list| {
4050 if (shdr.sh_type == elf.SHT_NOBITS) continue;
4051 if (atom_list.atoms.items.len == 0) continue;
4052 atom_list.write(&buffer, &undefs, self) catch |err| switch (err) {
4053 error.UnsupportedCpuArch => {
4054 try self.reportUnsupportedCpuArch();
4055 return error.FlushFailure;
4056 },
4057 error.RelocFailure, error.RelaxFailure => has_reloc_errors = true,
4058 else => |e| return e,
4059 };
4060 }
4061
4062 try self.reportUndefinedSymbols(&undefs);
4063 if (has_reloc_errors) return error.FlushFailure;
40444064
4065 if (self.requiresThunks()) {
40454066 for (self.thunks.items) |th| {
40464067 const thunk_size = th.size(self);
40474068 try buffer.ensureUnusedCapacity(thunk_size);
......@@ -4993,7 +5014,7 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 {
49935014 return off;
49945015}
49955016
4996pub fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void {
5017fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void {
49975018 const gpa = self.base.comp.gpa;
49985019 const max_notes = 4;
49995020
......@@ -5061,7 +5082,7 @@ fn reportMissingLibraryError(
50615082 }
50625083}
50635084
5064pub fn reportUnsupportedCpuArch(self: *Elf) error{OutOfMemory}!void {
5085fn reportUnsupportedCpuArch(self: *Elf) error{OutOfMemory}!void {
50655086 var err = try self.base.addErrorWithNotes(0);
50665087 try err.addMsg("fatal linker error: unsupported CPU architecture {s}", .{
50675088 @tagName(self.getTarget().cpu.arch),
......@@ -5248,9 +5269,8 @@ fn fmtDumpState(
52485269 try writer.print("object({d}) : {}", .{ index, object.fmtPath() });
52495270 if (!object.alive) try writer.writeAll(" : [*]");
52505271 try writer.writeByte('\n');
5251 try writer.print("{}{}{}{}{}{}\n", .{
5272 try writer.print("{}{}{}{}{}\n", .{
52525273 object.fmtAtoms(self),
5253 object.fmtSectionChunks(self),
52545274 object.fmtCies(self),
52555275 object.fmtFdes(self),
52565276 object.fmtSymtab(self),
......@@ -5274,6 +5294,14 @@ fn fmtDumpState(
52745294 try writer.print("{}\n", .{linker_defined.fmtSymtab(self)});
52755295 }
52765296
5297 const slice = self.sections.slice();
5298 {
5299 try writer.writeAll("atom lists\n");
5300 for (slice.items(.shdr), slice.items(.atom_list_2), 0..) |shdr, atom_list, shndx| {
5301 try writer.print("shdr({d}) : {s} : {}", .{ shndx, self.getShString(shdr.sh_name), atom_list.fmt(self) });
5302 }
5303 }
5304
52775305 if (self.requiresThunks()) {
52785306 try writer.writeAll("thunks\n");
52795307 for (self.thunks.items, 0..) |th, index| {
......@@ -5295,7 +5323,7 @@ fn fmtDumpState(
52955323 }
52965324
52975325 try writer.writeAll("\nOutput shdrs\n");
5298 for (self.sections.items(.shdr), self.sections.items(.phndx), 0..) |shdr, phndx, shndx| {
5326 for (slice.items(.shdr), slice.items(.phndx), 0..) |shdr, phndx, shndx| {
52995327 try writer.print(" shdr({d}) : phdr({?d}) : {}\n", .{
53005328 shndx,
53015329 phndx,
......@@ -5549,8 +5577,14 @@ const Section = struct {
55495577 phndx: ?u32 = null,
55505578
55515579 /// List of atoms contributing to this section.
5580 /// TODO currently this is only used for relocations tracking in relocatable mode
5581 /// but will be merged with atom_list_2.
55525582 atom_list: std.ArrayListUnmanaged(Ref) = .{},
55535583
5584 /// List of atoms contributing to this section.
5585 /// This can be used by sections that require special handling such as init/fini array, etc.
5586 atom_list_2: AtomList = .{},
5587
55545588 /// Index of the last allocated atom in this section.
55555589 last_atom: Ref = .{ .index = 0, .file = 0 },
55565590
......@@ -5690,6 +5724,7 @@ const Air = @import("../Air.zig");
56905724const Allocator = std.mem.Allocator;
56915725const Archive = @import("Elf/Archive.zig");
56925726pub const Atom = @import("Elf/Atom.zig");
5727const AtomList = @import("Elf/AtomList.zig");
56935728const Cache = std.Build.Cache;
56945729const Path = Cache.Path;
56955730const Compilation = @import("../Compilation.zig");
src/link/Elf/Object.zig+4-272
......@@ -17,7 +17,6 @@ relocs: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},
1717atoms: std.ArrayListUnmanaged(Atom) = .{},
1818atoms_indexes: std.ArrayListUnmanaged(Atom.Index) = .{},
1919atoms_extra: std.ArrayListUnmanaged(u32) = .{},
20section_chunks: std.ArrayListUnmanaged(SectionChunk) = .{},
2120
2221comdat_groups: std.ArrayListUnmanaged(Elf.ComdatGroup) = .{},
2322comdat_group_data: std.ArrayListUnmanaged(u32) = .{},
......@@ -59,10 +58,6 @@ pub fn deinit(self: *Object, allocator: Allocator) void {
5958 self.atoms.deinit(allocator);
6059 self.atoms_indexes.deinit(allocator);
6160 self.atoms_extra.deinit(allocator);
62 for (self.section_chunks.items) |*chunk| {
63 chunk.deinit(allocator);
64 }
65 self.section_chunks.deinit(allocator);
6661 self.comdat_groups.deinit(allocator);
6762 self.comdat_group_data.deinit(allocator);
6863 self.relocs.deinit(allocator);
......@@ -952,166 +947,9 @@ pub fn initOutputSections(self: *Object, elf_file: *Elf) !void {
952947 .flags = shdr.sh_flags,
953948 .type = shdr.sh_type,
954949 });
955 const chunk = for (self.section_chunks.items) |*chunk| {
956 if (chunk.output_section_index == osec) break chunk;
957 } else blk: {
958 const chunk = try self.section_chunks.addOne(elf_file.base.comp.gpa);
959 chunk.* = .{ .output_section_index = osec };
960 break :blk chunk;
961 };
962 try chunk.atoms.append(elf_file.base.comp.gpa, atom_index);
963 }
964}
965
966pub fn allocateAtoms(self: *Object, elf_file: *Elf) !void {
967 for (self.section_chunks.items) |*chunk| {
968 chunk.updateSize(self);
969 }
970
971 for (self.section_chunks.items) |*chunk| {
972 const alloc_res = try elf_file.allocateChunk(.{
973 .shndx = chunk.output_section_index,
974 .size = chunk.size,
975 .alignment = chunk.alignment,
976 .requires_padding = false,
977 });
978 chunk.value = @intCast(alloc_res.value);
979
980 const slice = elf_file.sections.slice();
981 const shdr = &slice.items(.shdr)[chunk.output_section_index];
982 const last_atom_ref = &slice.items(.last_atom)[chunk.output_section_index];
983
984 const expand_section = if (elf_file.atom(alloc_res.placement)) |placement_atom|
985 placement_atom.nextAtom(elf_file) == null
986 else
987 true;
988 if (expand_section) last_atom_ref.* = chunk.lastAtom(self).ref();
989 shdr.sh_addralign = @max(shdr.sh_addralign, chunk.alignment.toByteUnits().?);
990
991 {
992 var idx: usize = 0;
993 while (idx < chunk.atoms.items.len) : (idx += 1) {
994 const curr_atom_ptr = self.atom(chunk.atoms.items[idx]).?;
995 if (idx > 0) {
996 curr_atom_ptr.prev_atom_ref = .{ .index = chunk.atoms.items[idx - 1], .file = self.index };
997 }
998 if (idx + 1 < chunk.atoms.items.len) {
999 curr_atom_ptr.next_atom_ref = .{ .index = chunk.atoms.items[idx + 1], .file = self.index };
1000 }
1001 }
1002 }
1003
1004 if (elf_file.atom(alloc_res.placement)) |placement_atom| {
1005 chunk.firstAtom(self).prev_atom_ref = placement_atom.ref();
1006 chunk.lastAtom(self).next_atom_ref = placement_atom.next_atom_ref;
1007 placement_atom.next_atom_ref = chunk.firstAtom(self).ref();
1008 }
1009
1010 // TODO if we had a link from Atom to parent Chunk we would not need to update Atom's value or osec index
1011 for (chunk.atoms.items) |atom_index| {
1012 const atom_ptr = self.atom(atom_index).?;
1013 atom_ptr.output_section_index = chunk.output_section_index;
1014 atom_ptr.value += chunk.value;
1015 }
1016 }
1017}
1018
1019pub fn writeAtoms(self: *Object, elf_file: *Elf) !void {
1020 const gpa = elf_file.base.comp.gpa;
1021
1022 var undefs = std.AutoArrayHashMap(Elf.SymbolResolver.Index, std.ArrayList(Elf.Ref)).init(gpa);
1023 defer {
1024 for (undefs.values()) |*refs| {
1025 refs.deinit();
1026 }
1027 undefs.deinit();
1028 }
1029
1030 var buffer = std.ArrayList(u8).init(gpa);
1031 defer buffer.deinit();
1032
1033 log.debug("writing atoms in {}", .{self.fmtPath()});
1034
1035 var has_reloc_errors = false;
1036 for (self.section_chunks.items) |chunk| {
1037 const osec = elf_file.sections.items(.shdr)[chunk.output_section_index];
1038 if (osec.sh_type == elf.SHT_NOBITS) continue;
1039
1040 log.debug(" in section '{s}'", .{elf_file.getShString(osec.sh_name)});
1041
1042 try buffer.ensureUnusedCapacity(chunk.size);
1043 buffer.appendNTimesAssumeCapacity(0, chunk.size);
1044
1045 for (chunk.atoms.items) |atom_index| {
1046 const atom_ptr = self.atom(atom_index).?;
1047 assert(atom_ptr.alive);
1048
1049 const offset = math.cast(usize, atom_ptr.value - chunk.value) orelse return error.Overflow;
1050 const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;
1051
1052 log.debug(" * atom({d}) at 0x{x}", .{ atom_index, chunk.offset(elf_file) + offset });
1053
1054 const code = try self.codeDecompressAlloc(elf_file, atom_index);
1055 defer gpa.free(code);
1056 const out_code = buffer.items[offset..][0..size];
1057 @memcpy(out_code, code);
1058
1059 const res = if (osec.sh_flags & elf.SHF_ALLOC == 0)
1060 atom_ptr.resolveRelocsNonAlloc(elf_file, out_code, &undefs)
1061 else
1062 atom_ptr.resolveRelocsAlloc(elf_file, out_code);
1063 _ = res catch |err| switch (err) {
1064 error.UnsupportedCpuArch => {
1065 try elf_file.reportUnsupportedCpuArch();
1066 return error.FlushFailure;
1067 },
1068 error.RelocFailure, error.RelaxFailure => has_reloc_errors = true,
1069 else => |e| return e,
1070 };
1071 }
1072
1073 try elf_file.base.file.?.pwriteAll(buffer.items, chunk.offset(elf_file));
1074 buffer.clearRetainingCapacity();
1075 }
1076
1077 try elf_file.reportUndefinedSymbols(&undefs);
1078 if (has_reloc_errors) return error.FlushFailure;
1079}
1080
1081pub fn writeAtomsRelocatable(self: *Object, elf_file: *Elf) !void {
1082 const gpa = elf_file.base.comp.gpa;
1083
1084 var buffer = std.ArrayList(u8).init(gpa);
1085 defer buffer.deinit();
1086
1087 log.debug("writing atoms in {}", .{self.fmtPath()});
1088
1089 for (self.section_chunks.items) |chunk| {
1090 const osec = elf_file.sections.items(.shdr)[chunk.output_section_index];
1091 if (osec.sh_type == elf.SHT_NOBITS) continue;
1092
1093 log.debug(" in section '{s}'", .{elf_file.getShString(osec.sh_name)});
1094
1095 try buffer.ensureUnusedCapacity(chunk.size);
1096 buffer.appendNTimesAssumeCapacity(0, chunk.size);
1097
1098 for (chunk.atoms.items) |atom_index| {
1099 const atom_ptr = self.atom(atom_index).?;
1100 assert(atom_ptr.alive);
1101
1102 const offset = math.cast(usize, atom_ptr.value - chunk.value) orelse return error.Overflow;
1103 const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;
1104
1105 log.debug(" * atom({d}) at 0x{x}", .{ atom_index, chunk.offset(elf_file) + offset });
1106
1107 const code = try self.codeDecompressAlloc(elf_file, atom_index);
1108 defer gpa.free(code);
1109 const out_code = buffer.items[offset..][0..size];
1110 @memcpy(out_code, code);
1111 }
1112
1113 try elf_file.base.file.?.pwriteAll(buffer.items, chunk.offset(elf_file));
1114 buffer.clearRetainingCapacity();
950 const atom_list = &elf_file.sections.items(.atom_list_2)[osec];
951 atom_list.output_section_index = osec;
952 try atom_list.atoms.append(elf_file.base.comp.gpa, atom_ptr.ref());
1115953 }
1116954}
1117955
......@@ -1585,29 +1423,6 @@ fn formatAtoms(
15851423 }
15861424}
15871425
1588pub fn fmtSectionChunks(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatSectionChunks) {
1589 return .{ .data = .{
1590 .object = self,
1591 .elf_file = elf_file,
1592 } };
1593}
1594
1595fn formatSectionChunks(
1596 ctx: FormatContext,
1597 comptime unused_fmt_string: []const u8,
1598 options: std.fmt.FormatOptions,
1599 writer: anytype,
1600) !void {
1601 _ = unused_fmt_string;
1602 _ = options;
1603 const object = ctx.object;
1604 const elf_file = ctx.elf_file;
1605 try writer.writeAll(" section chunks\n");
1606 for (object.section_chunks.items) |chunk| {
1607 try writer.print(" {}\n", .{chunk.fmt(elf_file)});
1608 }
1609}
1610
16111426pub fn fmtCies(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatCies) {
16121427 return .{ .data = .{
16131428 .object = self,
......@@ -1709,90 +1524,6 @@ const InArchive = struct {
17091524 size: u32,
17101525};
17111526
1712const SectionChunk = struct {
1713 value: i64 = 0,
1714 size: u64 = 0,
1715 alignment: Atom.Alignment = .@"1",
1716 output_section_index: u32 = 0,
1717 atoms: std.ArrayListUnmanaged(Atom.Index) = .{},
1718
1719 fn deinit(chunk: *SectionChunk, allocator: Allocator) void {
1720 chunk.atoms.deinit(allocator);
1721 }
1722
1723 fn address(chunk: SectionChunk, elf_file: *Elf) i64 {
1724 const shdr = elf_file.sections.items(.shdr)[chunk.output_section_index];
1725 return @as(i64, @intCast(shdr.sh_addr)) + chunk.value;
1726 }
1727
1728 fn offset(chunk: SectionChunk, elf_file: *Elf) u64 {
1729 const shdr = elf_file.sections.items(.shdr)[chunk.output_section_index];
1730 return shdr.sh_offset + @as(u64, @intCast(chunk.value));
1731 }
1732
1733 fn updateSize(chunk: *SectionChunk, object: *Object) void {
1734 for (chunk.atoms.items) |atom_index| {
1735 const atom_ptr = object.atom(atom_index).?;
1736 assert(atom_ptr.alive);
1737 const off = atom_ptr.alignment.forward(chunk.size);
1738 const padding = off - chunk.size;
1739 atom_ptr.value = @intCast(off);
1740 chunk.size += padding + atom_ptr.size;
1741 chunk.alignment = chunk.alignment.max(atom_ptr.alignment);
1742 }
1743 }
1744
1745 fn firstAtom(chunk: SectionChunk, object: *Object) *Atom {
1746 assert(chunk.atoms.items.len > 0);
1747 return object.atom(chunk.atoms.items[0]).?;
1748 }
1749
1750 fn lastAtom(chunk: SectionChunk, object: *Object) *Atom {
1751 assert(chunk.atoms.items.len > 0);
1752 return object.atom(chunk.atoms.items[chunk.atoms.items.len - 1]).?;
1753 }
1754
1755 pub fn format(
1756 chunk: SectionChunk,
1757 comptime unused_fmt_string: []const u8,
1758 options: std.fmt.FormatOptions,
1759 writer: anytype,
1760 ) !void {
1761 _ = chunk;
1762 _ = unused_fmt_string;
1763 _ = options;
1764 _ = writer;
1765 @compileError("do not format SectionChunk directly");
1766 }
1767
1768 const FormatCtx = struct { SectionChunk, *Elf };
1769
1770 pub fn fmt(chunk: SectionChunk, elf_file: *Elf) std.fmt.Formatter(format2) {
1771 return .{ .data = .{ chunk, elf_file } };
1772 }
1773
1774 fn format2(
1775 ctx: FormatCtx,
1776 comptime unused_fmt_string: []const u8,
1777 options: std.fmt.FormatOptions,
1778 writer: anytype,
1779 ) !void {
1780 _ = unused_fmt_string;
1781 _ = options;
1782 const chunk, const elf_file = ctx;
1783 try writer.print("chunk : @{x} : shdr({d}) : align({x}) : size({x})", .{
1784 chunk.address(elf_file), chunk.output_section_index,
1785 chunk.alignment.toByteUnits() orelse 0, chunk.size,
1786 });
1787 try writer.writeAll(" : atoms{ ");
1788 for (chunk.atoms.items, 0..) |atom_index, i| {
1789 try writer.print("{d}", .{atom_index});
1790 if (i < chunk.atoms.items.len - 1) try writer.writeAll(", ");
1791 }
1792 try writer.writeAll(" }");
1793 }
1794};
1795
17961527const Object = @This();
17971528
17981529const std = @import("std");
......@@ -1807,6 +1538,7 @@ const mem = std.mem;
18071538const Allocator = mem.Allocator;
18081539const Archive = @import("Archive.zig");
18091540const Atom = @import("Atom.zig");
1541const AtomList = @import("AtomList.zig");
18101542const Cie = eh_frame.Cie;
18111543const Elf = @import("../Elf.zig");
18121544const Fde = eh_frame.Fde;
src/link/Elf/relocatable.zig+15-5
......@@ -353,11 +353,13 @@ fn initComdatGroups(elf_file: *Elf) !void {
353353}
354354
355355fn updateSectionSizes(elf_file: *Elf) !void {
356 for (elf_file.objects.items) |index| {
357 try elf_file.file(index).?.object.allocateAtoms(elf_file);
356 const slice = elf_file.sections.slice();
357 for (slice.items(.atom_list_2)) |*atom_list| {
358 if (atom_list.atoms.items.len == 0) continue;
359 atom_list.updateSize(elf_file);
360 try atom_list.allocate(elf_file);
358361 }
359362
360 const slice = elf_file.sections.slice();
361363 for (slice.items(.shdr), 0..) |*shdr, shndx| {
362364 const atom_list = slice.items(.atom_list)[shndx];
363365 if (shdr.sh_type != elf.SHT_RELA) continue;
......@@ -444,8 +446,16 @@ fn allocateAllocSections(elf_file: *Elf) !void {
444446}
445447
446448fn writeAtoms(elf_file: *Elf) !void {
447 for (elf_file.objects.items) |index| {
448 try elf_file.file(index).?.object.writeAtomsRelocatable(elf_file);
449 const gpa = elf_file.base.comp.gpa;
450
451 var buffer = std.ArrayList(u8).init(gpa);
452 defer buffer.deinit();
453
454 const slice = elf_file.sections.slice();
455 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, atom_list| {
456 if (shdr.sh_type == elf.SHT_NOBITS) continue;
457 if (atom_list.atoms.items.len == 0) continue;
458 try atom_list.writeRelocatable(&buffer, elf_file);
449459 }
450460}
451461