authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-09-01 13:51:08+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-09-04 13:34:25+02:00
log1ef96f05eb7806d7123919d30f4b672e82a64d75
treeab45f14dd5a53f7efd0fd047583010f7cf0b22c9
parent6ec5df3898d594dd97d1b557aa7bdde38a9998b6

elf: introduce SectionChunk - a container of atoms per object file


2 files changed, 119 insertions(+), 2 deletions(-)

src/link/Elf.zig+6-1
...@@ -3555,6 +3555,10 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {...@@ -3555,6 +3555,10 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {
3555}3555}
35563556
3557fn updateSectionSizes(self: *Elf) !void {3557fn updateSectionSizes(self: *Elf) !void {
3558 for (self.objects.items) |index| {
3559 try self.file(index).?.object.allocateAtoms(self);
3560 }
3561
3558 const slice = self.sections.slice();3562 const slice = self.sections.slice();
3559 for (slice.items(.shdr), slice.items(.atom_list)) |*shdr, atom_list| {3563 for (slice.items(.shdr), slice.items(.atom_list)) |*shdr, atom_list| {
3560 if (atom_list.items.len == 0) continue;3564 if (atom_list.items.len == 0) continue;
...@@ -5334,8 +5338,9 @@ fn fmtDumpState(...@@ -5334,8 +5338,9 @@ fn fmtDumpState(
5334 try writer.print("object({d}) : {}", .{ index, object.fmtPath() });5338 try writer.print("object({d}) : {}", .{ index, object.fmtPath() });
5335 if (!object.alive) try writer.writeAll(" : [*]");5339 if (!object.alive) try writer.writeAll(" : [*]");
5336 try writer.writeByte('\n');5340 try writer.writeByte('\n');
5337 try writer.print("{}{}{}{}{}\n", .{5341 try writer.print("{}{}{}{}{}{}\n", .{
5338 object.fmtAtoms(self),5342 object.fmtAtoms(self),
5343 object.fmtSectionChunks(self),
5339 object.fmtCies(self),5344 object.fmtCies(self),
5340 object.fmtFdes(self),5345 object.fmtFdes(self),
5341 object.fmtSymtab(self),5346 object.fmtSymtab(self),
src/link/Elf/Object.zig+113-1
...@@ -17,6 +17,7 @@ relocs: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},...@@ -17,6 +17,7 @@ relocs: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},
17atoms: std.ArrayListUnmanaged(Atom) = .{},17atoms: std.ArrayListUnmanaged(Atom) = .{},
18atoms_indexes: std.ArrayListUnmanaged(Atom.Index) = .{},18atoms_indexes: std.ArrayListUnmanaged(Atom.Index) = .{},
19atoms_extra: std.ArrayListUnmanaged(u32) = .{},19atoms_extra: std.ArrayListUnmanaged(u32) = .{},
20section_chunks: std.ArrayListUnmanaged(SectionChunk) = .{},
2021
21comdat_groups: std.ArrayListUnmanaged(Elf.ComdatGroup) = .{},22comdat_groups: std.ArrayListUnmanaged(Elf.ComdatGroup) = .{},
22comdat_group_data: std.ArrayListUnmanaged(u32) = .{},23comdat_group_data: std.ArrayListUnmanaged(u32) = .{},
...@@ -58,6 +59,10 @@ pub fn deinit(self: *Object, allocator: Allocator) void {...@@ -58,6 +59,10 @@ pub fn deinit(self: *Object, allocator: Allocator) void {
58 self.atoms.deinit(allocator);59 self.atoms.deinit(allocator);
59 self.atoms_indexes.deinit(allocator);60 self.atoms_indexes.deinit(allocator);
60 self.atoms_extra.deinit(allocator);61 self.atoms_extra.deinit(allocator);
62 for (self.section_chunks.items) |*chunk| {
63 chunk.deinit(allocator);
64 }
65 self.section_chunks.deinit(allocator);
61 self.comdat_groups.deinit(allocator);66 self.comdat_groups.deinit(allocator);
62 self.comdat_group_data.deinit(allocator);67 self.comdat_group_data.deinit(allocator);
63 self.relocs.deinit(allocator);68 self.relocs.deinit(allocator);
...@@ -933,11 +938,26 @@ pub fn initOutputSections(self: *Object, elf_file: *Elf) !void {...@@ -933,11 +938,26 @@ pub fn initOutputSections(self: *Object, elf_file: *Elf) !void {
933 const atom_ptr = self.atom(atom_index) orelse continue;938 const atom_ptr = self.atom(atom_index) orelse continue;
934 if (!atom_ptr.alive) continue;939 if (!atom_ptr.alive) continue;
935 const shdr = atom_ptr.inputShdr(elf_file);940 const shdr = atom_ptr.inputShdr(elf_file);
936 _ = try elf_file.initOutputSection(.{941 const osec = try elf_file.initOutputSection(.{
937 .name = self.getString(shdr.sh_name),942 .name = self.getString(shdr.sh_name),
938 .flags = shdr.sh_flags,943 .flags = shdr.sh_flags,
939 .type = shdr.sh_type,944 .type = shdr.sh_type,
940 });945 });
946 const chunk = for (self.section_chunks.items) |*chunk| {
947 if (chunk.output_section_index == osec) break chunk;
948 } else blk: {
949 const chunk = try self.section_chunks.addOne(elf_file.base.comp.gpa);
950 chunk.* = .{ .output_section_index = osec };
951 break :blk chunk;
952 };
953 try chunk.atoms.append(elf_file.base.comp.gpa, atom_index);
954 }
955}
956
957pub fn allocateAtoms(self: *Object, elf_file: *Elf) !void {
958 _ = elf_file;
959 for (self.section_chunks.items) |*chunk| {
960 chunk.updateSize(self);
941 }961 }
942}962}
943963
...@@ -1427,6 +1447,29 @@ fn formatAtoms(...@@ -1427,6 +1447,29 @@ fn formatAtoms(
1427 }1447 }
1428}1448}
14291449
1450pub fn fmtSectionChunks(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatSectionChunks) {
1451 return .{ .data = .{
1452 .object = self,
1453 .elf_file = elf_file,
1454 } };
1455}
1456
1457fn formatSectionChunks(
1458 ctx: FormatContext,
1459 comptime unused_fmt_string: []const u8,
1460 options: std.fmt.FormatOptions,
1461 writer: anytype,
1462) !void {
1463 _ = unused_fmt_string;
1464 _ = options;
1465 const object = ctx.object;
1466 const elf_file = ctx.elf_file;
1467 try writer.writeAll(" section chunks\n");
1468 for (object.section_chunks.items) |chunk| {
1469 try writer.print(" {}\n", .{chunk.fmt(elf_file)});
1470 }
1471}
1472
1430pub fn fmtCies(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatCies) {1473pub fn fmtCies(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatCies) {
1431 return .{ .data = .{1474 return .{ .data = .{
1432 .object = self,1475 .object = self,
...@@ -1528,6 +1571,75 @@ const InArchive = struct {...@@ -1528,6 +1571,75 @@ const InArchive = struct {
1528 size: u32,1571 size: u32,
1529};1572};
15301573
1574const SectionChunk = struct {
1575 value: i64 = 0,
1576 size: u64 = 0,
1577 alignment: Atom.Alignment = .@"1",
1578 output_section_index: u32 = 0,
1579 atoms: std.ArrayListUnmanaged(Atom.Index) = .{},
1580
1581 fn deinit(chunk: *SectionChunk, allocator: Allocator) void {
1582 chunk.atoms.deinit(allocator);
1583 }
1584
1585 fn address(chunk: SectionChunk, elf_file: *Elf) i64 {
1586 const shdr = elf_file.sections.items(.shdr)[chunk.output_section_index];
1587 return @as(i64, @intCast(shdr.sh_addr)) + chunk.value;
1588 }
1589
1590 fn updateSize(chunk: *SectionChunk, object: *Object) void {
1591 for (chunk.atoms.items) |atom_index| {
1592 const atom_ptr = object.atom(atom_index).?;
1593 assert(atom_ptr.alive);
1594 const offset = atom_ptr.alignment.forward(chunk.size);
1595 const padding = offset - chunk.size;
1596 atom_ptr.value = @intCast(offset);
1597 chunk.size += padding + atom_ptr.size;
1598 chunk.alignment = chunk.alignment.max(atom_ptr.alignment);
1599 }
1600 }
1601
1602 pub fn format(
1603 chunk: SectionChunk,
1604 comptime unused_fmt_string: []const u8,
1605 options: std.fmt.FormatOptions,
1606 writer: anytype,
1607 ) !void {
1608 _ = chunk;
1609 _ = unused_fmt_string;
1610 _ = options;
1611 _ = writer;
1612 @compileError("do not format SectionChunk directly");
1613 }
1614
1615 const FormatCtx = struct { SectionChunk, *Elf };
1616
1617 pub fn fmt(chunk: SectionChunk, elf_file: *Elf) std.fmt.Formatter(format2) {
1618 return .{ .data = .{ chunk, elf_file } };
1619 }
1620
1621 fn format2(
1622 ctx: FormatCtx,
1623 comptime unused_fmt_string: []const u8,
1624 options: std.fmt.FormatOptions,
1625 writer: anytype,
1626 ) !void {
1627 _ = unused_fmt_string;
1628 _ = options;
1629 const chunk, const elf_file = ctx;
1630 try writer.print("chunk : @{x} : shdr({d}) : align({x}) : size({x})", .{
1631 chunk.address(elf_file), chunk.output_section_index,
1632 chunk.alignment.toByteUnits() orelse 0, chunk.size,
1633 });
1634 try writer.writeAll(" : atoms{ ");
1635 for (chunk.atoms.items, 0..) |atom_index, i| {
1636 try writer.print("{d}", .{atom_index});
1637 if (i < chunk.atoms.items.len - 1) try writer.writeAll(", ");
1638 }
1639 try writer.writeAll(" }");
1640 }
1641};
1642
1531const Object = @This();1643const Object = @This();
15321644
1533const std = @import("std");1645const std = @import("std");