authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-09-01 16:49:16+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-09-01 16:49:16+02:00
log4eff0f4ea17da9ca8819d34fbf855596c3398497
treea3f208788b73351035ae3c33f6a05bf2e45a3310
parent7a99cd069afed01b8573274c20f685e61d0950c8

macho: fix condition for checking available size for an atom


2 files changed, 21 insertions(+), 22 deletions(-)

src/link/MachO.zig+19-18
......@@ -281,6 +281,10 @@ const DEFAULT_DYLD_PATH: [*:0]const u8 = "/usr/lib/dyld";
281281const minimum_text_block_size = 64;
282282pub const min_text_capacity = padToIdeal(minimum_text_block_size);
283283
284/// Virtual memory offset corresponds to the size of __PAGEZERO segment and start of
285/// __TEXT segment.
286const pagezero_vmsize: u64 = 0x100000000;
287
284288pub const Export = struct {
285289 sym_index: ?u32 = null,
286290};
......@@ -1903,13 +1907,19 @@ pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64
19031907 const vaddr = outer: {
19041908 if (!use_stage1) {
19051909 const sym = &self.locals.items[atom.local_sym_index];
1910 const needs_padding = blk: {
1911 // TODO is __text the only section that benefits from padding?
1912 if (match.seg == self.text_segment_cmd_index.? and
1913 match.sect == self.text_section_index.?) break :blk true;
1914 break :blk false;
1915 };
19061916
19071917 var atom_placement: ?*TextBlock = null;
19081918
19091919 // TODO converge with `allocateTextBlock` and handle free list
19101920 const vaddr = if (self.blocks.get(match)) |last| blk: {
19111921 const last_atom_sym = self.locals.items[last.local_sym_index];
1912 const ideal_capacity = padToIdeal(last.size);
1922 const ideal_capacity = if (needs_padding) padToIdeal(last.size) else last.size;
19131923 const ideal_capacity_end_vaddr = last_atom_sym.n_value + ideal_capacity;
19141924 const last_atom_alignment = try math.powi(u32, 2, atom.alignment);
19151925 const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, last_atom_alignment);
......@@ -1921,18 +1931,9 @@ pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64
19211931
19221932 const expand_section = atom_placement == null or atom_placement.?.next == null;
19231933 if (expand_section) {
1924 const needed_size = (vaddr + atom.size) - sect.addr;
1925 const end_addr = blk: {
1926 const next_ordinal = self.section_ordinals.getIndex(match).?; // Ordinals are +1 to begin with.
1927 const end_addr = if (self.section_ordinals.keys().len > next_ordinal) inner: {
1928 const next_match = self.section_ordinals.keys()[next_ordinal];
1929 const next_seg = self.load_commands.items[next_match.seg].Segment;
1930 const next_sect = next_seg.sections.items[next_match.sect];
1931 break :inner next_sect.addr;
1932 } else seg.inner.filesize;
1933 break :blk end_addr;
1934 };
1935 assert(needed_size <= end_addr); // TODO must expand the section
1934 const max_size = seg.allocatedSize(vaddr - pagezero_vmsize);
1935 log.debug(" (atom size 0x{x}, max available size 0x{x})", .{ atom.size, max_size });
1936 assert(atom.size <= max_size); // TODO must expand the section
19361937 }
19371938 const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);
19381939 sym.n_value = vaddr;
......@@ -3912,7 +3913,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
39123913 .Segment = .{
39133914 .inner = .{
39143915 .segname = makeStaticString("__PAGEZERO"),
3915 .vmsize = 0x100000000, // size always set to 4GB
3916 .vmsize = pagezero_vmsize,
39163917 },
39173918 },
39183919 });
......@@ -3932,7 +3933,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
39323933 .Segment = .{
39333934 .inner = .{
39343935 .segname = makeStaticString("__TEXT"),
3935 .vmaddr = 0x100000000, // always starts at 4GB
3936 .vmaddr = pagezero_vmsize,
39363937 .vmsize = needed_size,
39373938 .filesize = needed_size,
39383939 .maxprot = macho.VM_PROT_READ | macho.VM_PROT_EXECUTE,
......@@ -4452,8 +4453,6 @@ fn allocateSection(
44524453 const padding: ?u64 = if (segment_id == self.text_segment_cmd_index.?) self.header_pad else null;
44534454 const off = seg.findFreeSpace(size, alignment_pow_2, padding);
44544455
4455 assert(off + size <= seg.inner.fileoff + seg.inner.filesize); // TODO expand
4456
44574456 log.debug("found {s},{s} section free space 0x{x} to 0x{x}", .{
44584457 commands.segmentName(sect),
44594458 commands.sectionName(sect),
......@@ -4556,7 +4555,9 @@ fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64,
45564555 const expand_text_section = block_placement == null or block_placement.?.next == null;
45574556 if (expand_text_section) {
45584557 const needed_size = (vaddr + new_block_size) - text_section.addr;
4559 assert(needed_size <= text_segment.inner.filesize); // TODO must move the entire text section.
4558 const max_size = text_segment.allocatedSize(vaddr - pagezero_vmsize);
4559 log.debug(" (atom needed size 0x{x}, max available size 0x{x})", .{ needed_size, max_size });
4560 assert(needed_size <= max_size); // TODO must expand the section
45604561 _ = try self.blocks.put(self.base.allocator, match, text_block);
45614562 }
45624563 text_block.size = new_block_size;
src/link/MachO/commands.zig+2-4
......@@ -246,10 +246,8 @@ pub const SegmentCommand = struct {
246246 }
247247
248248 pub fn allocatedSize(self: SegmentCommand, start: u64) u64 {
249 assert(start > 0);
250 if (start == self.inner.fileoff)
251 return 0;
252 var min_pos: u64 = std.math.maxInt(u64);
249 assert(start >= self.inner.fileoff);
250 var min_pos: u64 = self.inner.fileoff + self.inner.filesize;
253251 for (self.sections.items) |section| {
254252 if (section.offset <= start) continue;
255253 if (section.offset < min_pos) min_pos = section.offset;