Commit 12187586d1
Changed files (3)
src
link
src/link/MachO/Object.zig
@@ -535,8 +535,11 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
// How does it tie with incremental space allocs?
const tseg = &zld.load_commands.items[match.seg].Segment;
const tsect = &tseg.sections.items[match.sect];
- tsect.size += block.size;
- tsect.@"align" = math.max(tsect.@"align", block.alignment);
+ const new_alignment = math.max(tsect.@"align", block.alignment);
+ const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment);
+ const new_size = mem.alignForwardGeneric(u64, tsect.size + block.size, new_alignment_pow_2);
+ tsect.size = new_size;
+ tsect.@"align" = new_alignment;
if (zld.blocks.getPtr(match)) |last| {
last.*.next = block;
@@ -621,8 +624,11 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
// How does it tie with incremental space allocs?
const tseg = &zld.load_commands.items[match.seg].Segment;
const tsect = &tseg.sections.items[match.sect];
- tsect.size += block.size;
- tsect.@"align" = math.max(tsect.@"align", block.alignment);
+ const new_alignment = math.max(tsect.@"align", block.alignment);
+ const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment);
+ const new_size = mem.alignForwardGeneric(u64, tsect.size + block.size, new_alignment_pow_2);
+ tsect.size = new_size;
+ tsect.@"align" = new_alignment;
if (zld.blocks.getPtr(match)) |last| {
last.*.next = block;
src/link/MachO/reloc.zig
@@ -52,7 +52,7 @@ pub const Relocation = struct {
pub fn resolve(self: Unsigned, base: Relocation, source_addr: u64, target_addr: u64) !void {
const addend = if (self.source_sect_addr) |addr|
- self.addend - addr
+ self.addend - @intCast(i64, addr)
else
self.addend;
@@ -86,13 +86,13 @@ pub const Relocation = struct {
arch: Arch,
pub fn resolve(self: Branch, base: Relocation, source_addr: u64, target_addr: u64) !void {
- switch (arch) {
+ switch (self.arch) {
.aarch64 => {
const displacement = try math.cast(i28, @intCast(i64, target_addr) - @intCast(i64, source_addr));
var inst = aarch64.Instruction{
.unconditional_branch_immediate = mem.bytesToValue(
meta.TagPayload(
- aarch.Instruction,
+ aarch64.Instruction,
aarch64.Instruction.unconditional_branch_immediate,
),
base.block.code[base.offset..][0..4],
@@ -236,13 +236,15 @@ pub const Relocation = struct {
},
.got => {
const narrowed = @truncate(u12, target_addr);
- var inst = mem.bytesToValue(
- meta.TagPayload(
- aarch64.Instruction,
- aarch64.Instruction.load_store_register,
+ var inst: aarch64.Instruction = .{
+ .load_store_register = mem.bytesToValue(
+ meta.TagPayload(
+ aarch64.Instruction,
+ aarch64.Instruction.load_store_register,
+ ),
+ base.block.code[base.offset..][0..4],
),
- base.block.code[base.offset..][0..4],
- );
+ };
const offset = try math.divExact(u12, narrowed, 8);
inst.load_store_register.offset = offset;
mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], inst.toU32());
@@ -408,14 +410,12 @@ pub const Relocation = struct {
break :blk sym.payload.regular.address + self.offset;
};
const target_addr = blk: {
- const is_via_got = inner: {
- switch (self.payload) {
- .pointer_to_got => break :inner true,
- .page => |page| page.kind == .got,
- .page_off => |page_off| page_off == .got,
- .load => {},
- else => break :inner false,
- }
+ const is_via_got = switch (self.payload) {
+ .pointer_to_got => true,
+ .page => |page| page.kind == .got,
+ .page_off => |page_off| page_off.kind == .got,
+ .load => |load| load.kind == .got,
+ else => false,
};
if (is_via_got) {
@@ -459,6 +459,11 @@ pub const Relocation = struct {
},
}
};
+
+ log.warn("relocating {}", .{self});
+ log.warn(" | source_addr = 0x{x}", .{source_addr});
+ log.warn(" | target_addr = 0x{x}", .{target_addr});
+
switch (self.payload) {
.unsigned => |unsigned| try unsigned.resolve(self, source_addr, target_addr),
.branch => |branch| try branch.resolve(self, source_addr, target_addr),
src/link/MachO/Zld.zig
@@ -173,6 +173,12 @@ pub const TextBlock = struct {
self.tlv_offsets.deinit();
}
+ pub fn resolveRelocs(self: *TextBlock, zld: *Zld) !void {
+ for (self.relocs.items) |rel| {
+ try rel.resolve(zld);
+ }
+ }
+
pub fn print_this(self: *const TextBlock, zld: *Zld) void {
log.warn("TextBlock", .{});
log.warn(" | {}: {}", .{ self.local_sym_index, zld.locals.items[self.local_sym_index] });
@@ -328,11 +334,10 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
const sect = seg.sections.items[entry.key_ptr.sect];
log.warn("\n\n{s},{s} contents:", .{ segmentName(sect), sectionName(sect) });
- log.warn("{}", .{sect});
+ log.warn(" {}", .{sect});
entry.value_ptr.*.print(self);
}
- return error.TODO;
- // try self.flush();
+ try self.flush();
}
fn parseInputFiles(self: *Zld, files: []const []const u8, syslibroot: ?[]const u8) !void {
@@ -1041,6 +1046,8 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void {
}
fn allocateTextBlocks(self: *Zld) !void {
+ log.warn("allocating text blocks", .{});
+
var it = self.blocks.iterator();
while (it.next()) |entry| {
const match = entry.key_ptr.*;
@@ -1050,13 +1057,34 @@ fn allocateTextBlocks(self: *Zld) !void {
const sect = seg.sections.items[match.sect];
var base_addr: u64 = sect.addr + sect.size;
+ log.warn(" within section {s},{s}", .{ segmentName(sect), sectionName(sect) });
+ log.warn(" {}", .{sect});
+
while (true) {
- base_addr -= block.size;
+ const block_alignment = try math.powi(u32, 2, block.alignment);
+ base_addr = mem.alignBackwardGeneric(u64, base_addr - block.size, block_alignment);
const sym = self.locals.items[block.local_sym_index];
assert(sym.payload == .regular);
sym.payload.regular.address = base_addr;
+ log.warn(" {s}: start=0x{x}, end=0x{x}, size={}, align={}", .{
+ sym.name,
+ base_addr,
+ base_addr + block.size,
+ block.size,
+ block.alignment,
+ });
+
+ // Update each alias (if any)
+ if (block.aliases) |aliases| {
+ for (aliases) |index| {
+ const alias_sym = self.locals.items[index];
+ assert(alias_sym.payload == .regular);
+ alias_sym.payload.regular.address = base_addr;
+ }
+ }
+
// Update each symbol contained within the TextBlock
if (block.contained) |contained| {
for (contained) |sym_at_off| {
@@ -1073,6 +1101,37 @@ fn allocateTextBlocks(self: *Zld) !void {
}
}
+fn writeTextBlocks(self: *Zld) !void {
+ var it = self.blocks.iterator();
+ while (it.next()) |entry| {
+ const match = entry.key_ptr.*;
+ var block: *TextBlock = entry.value_ptr.*;
+
+ const seg = self.load_commands.items[match.seg].Segment;
+ const sect = seg.sections.items[match.sect];
+
+ log.warn("writing text blocks for section {s},{s}", .{ segmentName(sect), sectionName(sect) });
+
+ var code = try self.allocator.alloc(u8, sect.size);
+ defer self.allocator.free(code);
+
+ var base_off: u64 = sect.size;
+
+ while (true) {
+ base_off -= block.size;
+
+ try block.resolveRelocs(self);
+ mem.copy(u8, code[base_off..][0..block.size], block.code);
+
+ if (block.prev) |prev| {
+ block = prev;
+ } else break;
+ }
+
+ try self.file.?.pwriteAll(code, sect.offset);
+ }
+}
+
fn writeStubHelperCommon(self: *Zld) !void {
const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
const stub_helper = &text_segment.sections.items[self.stub_helper_section_index.?];
@@ -1941,104 +2000,105 @@ fn addRpaths(self: *Zld, rpaths: []const []const u8) !void {
}
fn flush(self: *Zld) !void {
- try self.writeStubHelperCommon();
-
- if (self.common_section_index) |index| {
- const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
- const sect = &seg.sections.items[index];
- sect.offset = 0;
- }
-
- if (self.bss_section_index) |index| {
- const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
- const sect = &seg.sections.items[index];
- sect.offset = 0;
- }
-
- if (self.tlv_bss_section_index) |index| {
- const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
- const sect = &seg.sections.items[index];
- sect.offset = 0;
- }
-
- if (self.tlv_section_index) |index| {
- const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
- const sect = &seg.sections.items[index];
-
- var buffer = try self.allocator.alloc(u8, @intCast(usize, sect.size));
- defer self.allocator.free(buffer);
- _ = try self.file.?.preadAll(buffer, sect.offset);
-
- var stream = std.io.fixedBufferStream(buffer);
- var writer = stream.writer();
-
- std.sort.sort(TlvOffset, self.threadlocal_offsets.items, {}, TlvOffset.cmp);
-
- const seek_amt = 2 * @sizeOf(u64);
- for (self.threadlocal_offsets.items) |tlv| {
- try writer.context.seekBy(seek_amt);
- try writer.writeIntLittle(u64, tlv.offset);
- }
-
- try self.file.?.pwriteAll(buffer, sect.offset);
- }
-
- if (self.mod_init_func_section_index) |index| {
- const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
- const sect = &seg.sections.items[index];
-
- var initializers = std.ArrayList(u64).init(self.allocator);
- defer initializers.deinit();
-
- for (self.objects.items) |object| {
- for (object.initializers.items) |sym_id| {
- const address = object.symbols.items[sym_id].payload.regular.address;
- try initializers.append(address);
- }
- }
-
- _ = try self.file.?.pwriteAll(mem.sliceAsBytes(initializers.items), sect.offset);
- sect.size = @intCast(u32, initializers.items.len * @sizeOf(u64));
- }
-
- try self.writeGotEntries();
- try self.setEntryPoint();
- try self.writeRebaseInfoTable();
- try self.writeBindInfoTable();
- try self.writeLazyBindInfoTable();
- try self.writeExportInfo();
- try self.writeDataInCode();
-
- {
- const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
- const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
- symtab.symoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize);
- }
-
- try self.writeSymbolTable();
- try self.writeStringTable();
-
- {
- // Seal __LINKEDIT size
- const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
- seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?);
- }
-
- if (self.target.?.cpu.arch == .aarch64) {
- try self.writeCodeSignaturePadding();
- }
-
- try self.writeLoadCommands();
- try self.writeHeader();
-
- if (self.target.?.cpu.arch == .aarch64) {
- try self.writeCodeSignature();
- }
-
- if (comptime std.Target.current.isDarwin() and std.Target.current.cpu.arch == .aarch64) {
- const out_path = self.output.?.path;
- try fs.cwd().copyFile(out_path, fs.cwd(), out_path, .{});
- }
+ try self.writeTextBlocks();
+ // try self.writeStubHelperCommon();
+
+ // if (self.common_section_index) |index| {
+ // const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
+ // const sect = &seg.sections.items[index];
+ // sect.offset = 0;
+ // }
+
+ // if (self.bss_section_index) |index| {
+ // const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
+ // const sect = &seg.sections.items[index];
+ // sect.offset = 0;
+ // }
+
+ // if (self.tlv_bss_section_index) |index| {
+ // const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
+ // const sect = &seg.sections.items[index];
+ // sect.offset = 0;
+ // }
+
+ // if (self.tlv_section_index) |index| {
+ // const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
+ // const sect = &seg.sections.items[index];
+
+ // var buffer = try self.allocator.alloc(u8, @intCast(usize, sect.size));
+ // defer self.allocator.free(buffer);
+ // _ = try self.file.?.preadAll(buffer, sect.offset);
+
+ // var stream = std.io.fixedBufferStream(buffer);
+ // var writer = stream.writer();
+
+ // std.sort.sort(TlvOffset, self.threadlocal_offsets.items, {}, TlvOffset.cmp);
+
+ // const seek_amt = 2 * @sizeOf(u64);
+ // for (self.threadlocal_offsets.items) |tlv| {
+ // try writer.context.seekBy(seek_amt);
+ // try writer.writeIntLittle(u64, tlv.offset);
+ // }
+
+ // try self.file.?.pwriteAll(buffer, sect.offset);
+ // }
+
+ // if (self.mod_init_func_section_index) |index| {
+ // const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
+ // const sect = &seg.sections.items[index];
+
+ // var initializers = std.ArrayList(u64).init(self.allocator);
+ // defer initializers.deinit();
+
+ // for (self.objects.items) |object| {
+ // for (object.initializers.items) |sym_id| {
+ // const address = object.symbols.items[sym_id].payload.regular.address;
+ // try initializers.append(address);
+ // }
+ // }
+
+ // _ = try self.file.?.pwriteAll(mem.sliceAsBytes(initializers.items), sect.offset);
+ // sect.size = @intCast(u32, initializers.items.len * @sizeOf(u64));
+ // }
+
+ // try self.writeGotEntries();
+ // try self.setEntryPoint();
+ // try self.writeRebaseInfoTable();
+ // try self.writeBindInfoTable();
+ // try self.writeLazyBindInfoTable();
+ // try self.writeExportInfo();
+ // try self.writeDataInCode();
+
+ // {
+ // const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
+ // const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
+ // symtab.symoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize);
+ // }
+
+ // try self.writeSymbolTable();
+ // try self.writeStringTable();
+
+ // {
+ // // Seal __LINKEDIT size
+ // const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
+ // seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?);
+ // }
+
+ // if (self.target.?.cpu.arch == .aarch64) {
+ // try self.writeCodeSignaturePadding();
+ // }
+
+ // try self.writeLoadCommands();
+ // try self.writeHeader();
+
+ // if (self.target.?.cpu.arch == .aarch64) {
+ // try self.writeCodeSignature();
+ // }
+
+ // if (comptime std.Target.current.isDarwin() and std.Target.current.cpu.arch == .aarch64) {
+ // const out_path = self.output.?.path;
+ // try fs.cwd().copyFile(out_path, fs.cwd(), out_path, .{});
+ // }
}
fn writeGotEntries(self: *Zld) !void {