authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-08-02 22:15:07+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-08-03 21:19:41+02:00
log90e326827062fc7899d02516cdaffa7da8366077
tree8709238e09db8a89bad1e2414c7e833861f10bb7
parent421d3e8d2822e979c1a2d5e7aaa5859499bc2146

macho: do not preempt segment headers; do it when commiting to file

This way, tracking segment-to-section mapping becomes a lot easier since it's effectively just start index plus number of sections defined within the segment. If a section becomes empty however care needs to be taken to remove the header upon committing to the final binary.

3 files changed, 35 insertions(+), 13 deletions(-)

src/link/MachO.zig+18-5
......@@ -4888,13 +4888,26 @@ fn getSegmentAllocBase(self: MachO, indices: []const ?u8) struct { vmaddr: u64,
48884888
48894889fn writeSegmentHeaders(self: *MachO, ncmds: *u32, writer: anytype) !void {
48904890 for (self.segments.items) |seg, i| {
4891 if (seg.nsects == 0 and
4892 (mem.eql(u8, seg.segName(), "__DATA_CONST") or
4893 mem.eql(u8, seg.segName(), "__DATA"))) continue;
4894 try writer.writeStruct(seg);
4895
48964891 const indexes = self.getSectionIndexes(@intCast(u8, i));
4892 var out_seg = seg;
4893 out_seg.cmdsize = @sizeOf(macho.segment_command_64);
4894 out_seg.nsects = 0;
4895
4896 // Update section headers count; any section with size of 0 is excluded
4897 // since it doesn't have any data in the final binary file.
4898 for (self.sections.items(.header)[indexes.start..indexes.end]) |header| {
4899 if (header.size == 0) continue;
4900 out_seg.cmdsize += @sizeOf(macho.section_64);
4901 out_seg.nsects += 1;
4902 }
4903
4904 if (out_seg.nsects == 0 and
4905 (mem.eql(u8, out_seg.segName(), "__DATA_CONST") or
4906 mem.eql(u8, out_seg.segName(), "__DATA"))) continue;
4907
4908 try writer.writeStruct(out_seg);
48974909 for (self.sections.items(.header)[indexes.start..indexes.end]) |header| {
4910 if (header.size == 0) continue;
48984911 try writer.writeStruct(header);
48994912 }
49004913
src/link/MachO/DebugSymbols.zig+17-5
......@@ -367,16 +367,28 @@ fn writeSegmentHeaders(self: *DebugSymbols, ncmds: *u32, writer: anytype) !void
367367 // Write segment/section headers from the binary file first.
368368 const end = self.base.linkedit_segment_cmd_index.?;
369369 for (self.base.segments.items[0..end]) |seg, i| {
370 if (seg.nsects == 0 and
371 (mem.eql(u8, seg.segName(), "__DATA_CONST") or
372 mem.eql(u8, seg.segName(), "__DATA"))) continue;
370 const indexes = self.base.getSectionIndexes(@intCast(u8, i));
373371 var out_seg = seg;
374372 out_seg.fileoff = 0;
375373 out_seg.filesize = 0;
376 try writer.writeStruct(out_seg);
374 out_seg.cmdsize = @sizeOf(macho.segment_command_64);
375 out_seg.nsects = 0;
377376
378 const indexes = self.base.getSectionIndexes(@intCast(u8, i));
377 // Update section headers count; any section with size of 0 is excluded
378 // since it doesn't have any data in the final binary file.
379 for (self.base.sections.items(.header)[indexes.start..indexes.end]) |header| {
380 if (header.size == 0) continue;
381 out_seg.cmdsize += @sizeOf(macho.section_64);
382 out_seg.nsects += 1;
383 }
384
385 if (out_seg.nsects == 0 and
386 (mem.eql(u8, out_seg.segName(), "__DATA_CONST") or
387 mem.eql(u8, out_seg.segName(), "__DATA"))) continue;
388
389 try writer.writeStruct(out_seg);
379390 for (self.base.sections.items(.header)[indexes.start..indexes.end]) |header| {
391 if (header.size == 0) continue;
380392 var out_header = header;
381393 out_header.offset = 0;
382394 try writer.writeStruct(out_header);
src/link/MachO/dead_strip.zig-3
......@@ -43,9 +43,6 @@ fn removeAtomFromSection(atom: *Atom, match: u8, macho_file: *MachO) void {
4343 // The section will be GCed in the next step.
4444 section.last_atom = null;
4545 section.header.size = 0;
46 const segment = &macho_file.segments.items[section.segment_index];
47 segment.cmdsize -= @sizeOf(macho.section_64);
48 segment.nsects -= 1;
4946 }
5047 }
5148