aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/link/MachO.zig37
-rw-r--r--src/link/MachO/commands.zig6
2 files changed, 21 insertions, 22 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index e7ca3f9d6a..0892053a4f 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -281,6 +281,10 @@ const DEFAULT_DYLD_PATH: [*:0]const u8 = "/usr/lib/dyld";
const minimum_text_block_size = 64;
pub const min_text_capacity = padToIdeal(minimum_text_block_size);
+/// Virtual memory offset corresponds to the size of __PAGEZERO segment and start of
+/// __TEXT segment.
+const pagezero_vmsize: u64 = 0x100000000;
+
pub const Export = struct {
sym_index: ?u32 = null,
};
@@ -1903,13 +1907,19 @@ pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64
const vaddr = outer: {
if (!use_stage1) {
const sym = &self.locals.items[atom.local_sym_index];
+ const needs_padding = blk: {
+ // TODO is __text the only section that benefits from padding?
+ if (match.seg == self.text_segment_cmd_index.? and
+ match.sect == self.text_section_index.?) break :blk true;
+ break :blk false;
+ };
var atom_placement: ?*TextBlock = null;
// TODO converge with `allocateTextBlock` and handle free list
const vaddr = if (self.blocks.get(match)) |last| blk: {
const last_atom_sym = self.locals.items[last.local_sym_index];
- const ideal_capacity = padToIdeal(last.size);
+ const ideal_capacity = if (needs_padding) padToIdeal(last.size) else last.size;
const ideal_capacity_end_vaddr = last_atom_sym.n_value + ideal_capacity;
const last_atom_alignment = try math.powi(u32, 2, atom.alignment);
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
const expand_section = atom_placement == null or atom_placement.?.next == null;
if (expand_section) {
- const needed_size = (vaddr + atom.size) - sect.addr;
- const end_addr = blk: {
- const next_ordinal = self.section_ordinals.getIndex(match).?; // Ordinals are +1 to begin with.
- const end_addr = if (self.section_ordinals.keys().len > next_ordinal) inner: {
- const next_match = self.section_ordinals.keys()[next_ordinal];
- const next_seg = self.load_commands.items[next_match.seg].Segment;
- const next_sect = next_seg.sections.items[next_match.sect];
- break :inner next_sect.addr;
- } else seg.inner.filesize;
- break :blk end_addr;
- };
- assert(needed_size <= end_addr); // TODO must expand the section
+ const max_size = seg.allocatedSize(vaddr - pagezero_vmsize);
+ log.debug(" (atom size 0x{x}, max available size 0x{x})", .{ atom.size, max_size });
+ assert(atom.size <= max_size); // TODO must expand the section
}
const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);
sym.n_value = vaddr;
@@ -3912,7 +3913,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
.Segment = .{
.inner = .{
.segname = makeStaticString("__PAGEZERO"),
- .vmsize = 0x100000000, // size always set to 4GB
+ .vmsize = pagezero_vmsize,
},
},
});
@@ -3932,7 +3933,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
.Segment = .{
.inner = .{
.segname = makeStaticString("__TEXT"),
- .vmaddr = 0x100000000, // always starts at 4GB
+ .vmaddr = pagezero_vmsize,
.vmsize = needed_size,
.filesize = needed_size,
.maxprot = macho.VM_PROT_READ | macho.VM_PROT_EXECUTE,
@@ -4452,8 +4453,6 @@ fn allocateSection(
const padding: ?u64 = if (segment_id == self.text_segment_cmd_index.?) self.header_pad else null;
const off = seg.findFreeSpace(size, alignment_pow_2, padding);
- assert(off + size <= seg.inner.fileoff + seg.inner.filesize); // TODO expand
-
log.debug("found {s},{s} section free space 0x{x} to 0x{x}", .{
commands.segmentName(sect),
commands.sectionName(sect),
@@ -4556,7 +4555,9 @@ fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64,
const expand_text_section = block_placement == null or block_placement.?.next == null;
if (expand_text_section) {
const needed_size = (vaddr + new_block_size) - text_section.addr;
- assert(needed_size <= text_segment.inner.filesize); // TODO must move the entire text section.
+ const max_size = text_segment.allocatedSize(vaddr - pagezero_vmsize);
+ log.debug(" (atom needed size 0x{x}, max available size 0x{x})", .{ needed_size, max_size });
+ assert(needed_size <= max_size); // TODO must expand the section
_ = try self.blocks.put(self.base.allocator, match, text_block);
}
text_block.size = new_block_size;
diff --git a/src/link/MachO/commands.zig b/src/link/MachO/commands.zig
index ff7c5e841b..7bb1b12c32 100644
--- a/src/link/MachO/commands.zig
+++ b/src/link/MachO/commands.zig
@@ -246,10 +246,8 @@ pub const SegmentCommand = struct {
}
pub fn allocatedSize(self: SegmentCommand, start: u64) u64 {
- assert(start > 0);
- if (start == self.inner.fileoff)
- return 0;
- var min_pos: u64 = std.math.maxInt(u64);
+ assert(start >= self.inner.fileoff);
+ var min_pos: u64 = self.inner.fileoff + self.inner.filesize;
for (self.sections.items) |section| {
if (section.offset <= start) continue;
if (section.offset < min_pos) min_pos = section.offset;