mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
macho: make atom address relative wrt defining section
This commit is contained in:
parent
e10a2018a7
commit
9fc1685c1c
@ -636,7 +636,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
|
||||
return error.FlushFailure;
|
||||
},
|
||||
};
|
||||
const file_offset = sect.offset + atom.value - sect.addr;
|
||||
const file_offset = sect.offset + atom.value;
|
||||
atom.resolveRelocs(self, code) catch |err| switch (err) {
|
||||
error.ResolveFailed => has_resolve_error = true,
|
||||
else => |e| {
|
||||
@ -2393,16 +2393,7 @@ fn allocateSegments(self: *MachO) void {
|
||||
}
|
||||
|
||||
pub fn allocateAtoms(self: *MachO) void {
|
||||
const slice = self.sections.slice();
|
||||
for (slice.items(.header), slice.items(.atoms)) |header, atoms| {
|
||||
if (atoms.items.len == 0) continue;
|
||||
for (atoms.items) |atom_index| {
|
||||
const atom = self.getAtom(atom_index).?;
|
||||
assert(atom.flags.alive);
|
||||
atom.value += header.addr;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: redo this like atoms
|
||||
for (self.thunks.items) |*thunk| {
|
||||
const header = self.sections.items(.header)[thunk.out_n_sect];
|
||||
thunk.value += header.addr;
|
||||
@ -2603,7 +2594,7 @@ fn writeAtoms(self: *MachO) !void {
|
||||
for (atoms.items) |atom_index| {
|
||||
const atom = self.getAtom(atom_index).?;
|
||||
assert(atom.flags.alive);
|
||||
const off = math.cast(usize, atom.value - header.addr) orelse return error.Overflow;
|
||||
const off = math.cast(usize, atom.value) orelse return error.Overflow;
|
||||
const atom_size = math.cast(usize, atom.size) orelse return error.Overflow;
|
||||
try atom.getData(self, buffer[off..][0..atom_size]);
|
||||
atom.resolveRelocs(self, buffer[off..][0..atom_size]) catch |err| switch (err) {
|
||||
@ -2825,7 +2816,7 @@ pub fn writeDataInCode(self: *MachO, base_address: u64, off: u32) !u32 {
|
||||
|
||||
if (atom.flags.alive) for (in_dices[start_dice..next_dice]) |dice| {
|
||||
dices.appendAssumeCapacity(.{
|
||||
.offset = @intCast(atom.value + dice.offset - start_off - base_address),
|
||||
.offset = @intCast(atom.getAddress(self) + dice.offset - start_off - base_address),
|
||||
.length = dice.length,
|
||||
.kind = dice.kind,
|
||||
});
|
||||
@ -3318,7 +3309,7 @@ fn allocatedSize(self: *MachO, start: u64) u64 {
|
||||
return min_pos - start;
|
||||
}
|
||||
|
||||
fn allocatedVirtualSize(self: *MachO, start: u64) u64 {
|
||||
fn allocatedSizeVirtual(self: *MachO, start: u64) u64 {
|
||||
if (start == 0) return 0;
|
||||
var min_pos: u64 = std.math.maxInt(u64);
|
||||
for (self.segments.items) |seg| {
|
||||
@ -3518,22 +3509,39 @@ pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void {
|
||||
sect.size = 0;
|
||||
|
||||
// Must move the entire section.
|
||||
const alignment = if (self.base.isRelocatable())
|
||||
try math.powi(u32, 2, sect.@"align")
|
||||
else
|
||||
self.getPageSize();
|
||||
const new_offset = self.findFreeSpace(needed_size, alignment);
|
||||
if (self.base.isRelocatable()) {
|
||||
const alignment = try math.powi(u32, 2, sect.@"align");
|
||||
const new_offset = self.findFreeSpace(needed_size, alignment);
|
||||
const new_addr = self.findFreeSpaceVirtual(needed_size, alignment);
|
||||
|
||||
log.debug("new '{s},{s}' file offset 0x{x} to 0x{x}", .{
|
||||
sect.segName(),
|
||||
sect.sectName(),
|
||||
new_offset,
|
||||
new_offset + existing_size,
|
||||
});
|
||||
log.debug("new '{s},{s}' file offset 0x{x} to 0x{x} (0x{x} - 0x{x})", .{
|
||||
sect.segName(),
|
||||
sect.sectName(),
|
||||
new_offset,
|
||||
new_offset + existing_size,
|
||||
new_addr,
|
||||
new_addr + existing_size,
|
||||
});
|
||||
|
||||
try self.copyRangeAllZeroOut(sect.offset, new_offset, existing_size);
|
||||
try self.copyRangeAll(sect.offset, new_offset, existing_size);
|
||||
|
||||
sect.offset = @intCast(new_offset);
|
||||
sect.offset = @intCast(new_offset);
|
||||
sect.addr = new_addr;
|
||||
} else {
|
||||
const alignment = self.getPageSize();
|
||||
const new_offset = self.findFreeSpace(needed_size, alignment);
|
||||
|
||||
log.debug("new '{s},{s}' file offset 0x{x} to 0x{x}", .{
|
||||
sect.segName(),
|
||||
sect.sectName(),
|
||||
new_offset,
|
||||
new_offset + existing_size,
|
||||
});
|
||||
|
||||
try self.copyRangeAllZeroOut(sect.offset, new_offset, existing_size);
|
||||
|
||||
sect.offset = @intCast(new_offset);
|
||||
}
|
||||
}
|
||||
|
||||
sect.size = needed_size;
|
||||
@ -3547,7 +3555,7 @@ pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void {
|
||||
seg.filesize = needed_size;
|
||||
}
|
||||
|
||||
const mem_capacity = self.allocatedVirtualSize(seg.vmaddr);
|
||||
const mem_capacity = self.allocatedSizeVirtual(seg.vmaddr);
|
||||
if (needed_size > mem_capacity) {
|
||||
var err = try self.addErrorWithNotes(2);
|
||||
try err.addMsg(self, "fatal linker error: cannot expand segment seg({d})({s}) in virtual memory", .{
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/// Address allocated for this Atom.
|
||||
/// Address offset allocated for this Atom wrt to its section start address.
|
||||
value: u64 = 0,
|
||||
|
||||
/// Name of this Atom.
|
||||
@ -84,6 +84,11 @@ pub fn getInputAddress(self: Atom, macho_file: *MachO) u64 {
|
||||
return self.getInputSection(macho_file).addr + self.off;
|
||||
}
|
||||
|
||||
pub fn getAddress(self: Atom, macho_file: *MachO) u64 {
|
||||
const header = macho_file.sections.items(.header)[self.out_n_sect];
|
||||
return header.addr + self.value;
|
||||
}
|
||||
|
||||
pub fn getPriority(self: Atom, macho_file: *MachO) u64 {
|
||||
const file = self.getFile(macho_file);
|
||||
return (@as(u64, @intCast(file.getIndex())) << 32) | @as(u64, @intCast(self.n_sect));
|
||||
@ -189,14 +194,17 @@ pub fn initOutputSection(sect: macho.section_64, macho_file: *MachO) !u8 {
|
||||
/// File offset relocation happens transparently, so it is not included in
|
||||
/// this calculation.
|
||||
pub fn capacity(self: Atom, macho_file: *MachO) u64 {
|
||||
const next_value = if (macho_file.getAtom(self.next_index)) |next| next.value else std.math.maxInt(u32);
|
||||
return next_value - self.value;
|
||||
const next_addr = if (macho_file.getAtom(self.next_index)) |next|
|
||||
next.getAddress(macho_file)
|
||||
else
|
||||
std.math.maxInt(u32);
|
||||
return next_addr - self.getAddress(macho_file);
|
||||
}
|
||||
|
||||
pub fn freeListEligible(self: Atom, macho_file: *MachO) bool {
|
||||
// No need to keep a free list node for the last block.
|
||||
const next = macho_file.getAtom(self.next_index) orelse return false;
|
||||
const cap = next.value - self.value;
|
||||
const cap = next.getAddress(macho_file) - self.getAddress(macho_file);
|
||||
const ideal_cap = MachO.padToIdeal(self.size);
|
||||
if (cap <= ideal_cap) return false;
|
||||
const surplus = cap - ideal_cap;
|
||||
@ -263,15 +271,15 @@ pub fn allocate(self: *Atom, macho_file: *MachO) !void {
|
||||
atom_placement = last.atom_index;
|
||||
break :blk new_start_vaddr;
|
||||
} else {
|
||||
break :blk sect.addr;
|
||||
break :blk 0;
|
||||
}
|
||||
};
|
||||
|
||||
log.debug("allocated atom({d}) : '{s}' at 0x{x} to 0x{x}", .{
|
||||
self.atom_index,
|
||||
self.getName(macho_file),
|
||||
self.value,
|
||||
self.value + self.size,
|
||||
self.getAddress(macho_file),
|
||||
self.getAddress(macho_file) + self.size,
|
||||
});
|
||||
|
||||
const expand_section = if (atom_placement) |placement_index|
|
||||
@ -279,7 +287,7 @@ pub fn allocate(self: *Atom, macho_file: *MachO) !void {
|
||||
else
|
||||
true;
|
||||
if (expand_section) {
|
||||
const needed_size = (self.value + self.size) - sect.addr;
|
||||
const needed_size = self.value + self.size;
|
||||
try macho_file.growSection(self.out_n_sect, needed_size);
|
||||
last_atom_index.* = self.atom_index;
|
||||
|
||||
@ -544,7 +552,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {
|
||||
const name = self.getName(macho_file);
|
||||
const relocs = self.getRelocs(macho_file);
|
||||
|
||||
relocs_log.debug("{x}: {s}", .{ self.value, name });
|
||||
relocs_log.debug("{x}: {s}", .{ self.getAddress(macho_file), name });
|
||||
|
||||
var has_error = false;
|
||||
var stream = std.io.fixedBufferStream(buffer);
|
||||
@ -569,7 +577,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {
|
||||
try macho_file.reportParseError2(
|
||||
file.getIndex(),
|
||||
"{s}: 0x{x}: 0x{x}: failed to relax relocation: type {s}, target {s}",
|
||||
.{ name, self.value, rel.offset, @tagName(rel.type), target },
|
||||
.{ name, self.getAddress(macho_file), rel.offset, @tagName(rel.type), target },
|
||||
);
|
||||
has_error = true;
|
||||
},
|
||||
@ -604,7 +612,7 @@ fn resolveRelocInner(
|
||||
const rel_offset = math.cast(usize, rel.offset - self.off) orelse return error.Overflow;
|
||||
const seg_id = macho_file.sections.items(.segment_id)[self.out_n_sect];
|
||||
const seg = macho_file.segments.items[seg_id];
|
||||
const P = @as(i64, @intCast(self.value)) + @as(i64, @intCast(rel_offset));
|
||||
const P = @as(i64, @intCast(self.getAddress(macho_file))) + @as(i64, @intCast(rel_offset));
|
||||
const A = rel.addend + rel.getRelocAddend(cpu_arch);
|
||||
const S: i64 = @intCast(rel.getTargetAddress(macho_file));
|
||||
const G: i64 = @intCast(rel.getGotTargetAddress(macho_file));
|
||||
@ -919,7 +927,7 @@ const x86_64 = struct {
|
||||
var err = try macho_file.addErrorWithNotes(2);
|
||||
try err.addMsg(macho_file, "{s}: 0x{x}: 0x{x}: failed to relax relocation of type {s}", .{
|
||||
self.getName(macho_file),
|
||||
self.value,
|
||||
self.getAddress(macho_file),
|
||||
rel.offset,
|
||||
@tagName(rel.type),
|
||||
});
|
||||
@ -990,12 +998,11 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra
|
||||
|
||||
const cpu_arch = macho_file.getTarget().cpu.arch;
|
||||
const relocs = self.getRelocs(macho_file);
|
||||
const sect = macho_file.sections.items(.header)[self.out_n_sect];
|
||||
var stream = std.io.fixedBufferStream(code);
|
||||
|
||||
for (relocs) |rel| {
|
||||
const rel_offset = rel.offset - self.off;
|
||||
const r_address: i32 = math.cast(i32, self.value + rel_offset - sect.addr) orelse return error.Overflow;
|
||||
const r_address: i32 = math.cast(i32, self.value + rel_offset) orelse return error.Overflow;
|
||||
const r_symbolnum = r_symbolnum: {
|
||||
const r_symbolnum: u32 = switch (rel.tag) {
|
||||
.local => rel.getTargetAtom(macho_file).out_n_sect + 1,
|
||||
@ -1062,7 +1069,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra
|
||||
.x86_64 => {
|
||||
if (rel.meta.pcrel) {
|
||||
if (rel.tag == .local) {
|
||||
addend -= @as(i64, @intCast(self.value + rel_offset));
|
||||
addend -= @as(i64, @intCast(self.getAddress(macho_file) + rel_offset));
|
||||
} else {
|
||||
addend += 4;
|
||||
}
|
||||
@ -1144,7 +1151,7 @@ fn format2(
|
||||
const atom = ctx.atom;
|
||||
const macho_file = ctx.macho_file;
|
||||
try writer.print("atom({d}) : {s} : @{x} : sect({d}) : align({x}) : size({x}) : nreloc({d}) : thunk({d})", .{
|
||||
atom.atom_index, atom.getName(macho_file), atom.value,
|
||||
atom.atom_index, atom.getName(macho_file), atom.getAddress(macho_file),
|
||||
atom.out_n_sect, atom.alignment, atom.size,
|
||||
atom.getRelocs(macho_file).len, atom.thunk_index,
|
||||
});
|
||||
|
||||
@ -118,7 +118,7 @@ pub fn getAddress(symbol: Symbol, opts: struct {
|
||||
return symbol.getObjcStubsAddress(macho_file);
|
||||
}
|
||||
}
|
||||
if (symbol.getAtom(macho_file)) |atom| return atom.value + symbol.value;
|
||||
if (symbol.getAtom(macho_file)) |atom| return atom.getAddress(macho_file) + symbol.value;
|
||||
return symbol.value;
|
||||
}
|
||||
|
||||
@ -145,7 +145,7 @@ pub fn getObjcSelrefsAddress(symbol: Symbol, macho_file: *MachO) u64 {
|
||||
const extra = symbol.getExtra(macho_file).?;
|
||||
const atom = macho_file.getAtom(extra.objc_selrefs).?;
|
||||
assert(atom.flags.alive);
|
||||
return atom.value;
|
||||
return atom.getAddress(macho_file);
|
||||
}
|
||||
|
||||
pub fn getTlvPtrAddress(symbol: Symbol, macho_file: *MachO) u64 {
|
||||
|
||||
@ -154,7 +154,7 @@ pub fn getAtomData(self: ZigObject, macho_file: *MachO, atom: Atom, buffer: []u8
|
||||
@memset(buffer, 0);
|
||||
},
|
||||
else => {
|
||||
const file_offset = sect.offset + atom.value - sect.addr;
|
||||
const file_offset = sect.offset + atom.value;
|
||||
const amt = try macho_file.base.file.?.preadAll(buffer, file_offset);
|
||||
if (amt != buffer.len) return error.InputOutput;
|
||||
},
|
||||
@ -715,7 +715,7 @@ fn updateDeclCode(
|
||||
} else if (code.len < old_size) {
|
||||
atom.shrink(macho_file);
|
||||
} else if (macho_file.getAtom(atom.next_index) == null) {
|
||||
const needed_size = atom.value + code.len - sect.addr;
|
||||
const needed_size = atom.value + code.len;
|
||||
sect.size = needed_size;
|
||||
}
|
||||
} else {
|
||||
@ -733,7 +733,7 @@ fn updateDeclCode(
|
||||
}
|
||||
|
||||
if (!sect.isZerofill()) {
|
||||
const file_offset = sect.offset + atom.value - sect.addr;
|
||||
const file_offset = sect.offset + atom.value;
|
||||
try macho_file.base.file.?.pwriteAll(code, file_offset);
|
||||
}
|
||||
}
|
||||
@ -1036,7 +1036,7 @@ fn lowerConst(
|
||||
nlist.n_value = 0;
|
||||
|
||||
const sect = macho_file.sections.items(.header)[output_section_index];
|
||||
const file_offset = sect.offset + atom.value - sect.addr;
|
||||
const file_offset = sect.offset + atom.value;
|
||||
try macho_file.base.file.?.pwriteAll(code, file_offset);
|
||||
|
||||
return .{ .ok = sym_index };
|
||||
@ -1213,7 +1213,7 @@ fn updateLazySymbol(
|
||||
}
|
||||
|
||||
const sect = macho_file.sections.items(.header)[output_section_index];
|
||||
const file_offset = sect.offset + atom.value - sect.addr;
|
||||
const file_offset = sect.offset + atom.value;
|
||||
try macho_file.base.file.?.pwriteAll(code, file_offset);
|
||||
}
|
||||
|
||||
|
||||
@ -328,7 +328,7 @@ fn writeAtoms(macho_file: *MachO) !void {
|
||||
for (atoms.items) |atom_index| {
|
||||
const atom = macho_file.getAtom(atom_index).?;
|
||||
assert(atom.flags.alive);
|
||||
const off = math.cast(usize, atom.value - header.addr) orelse return error.Overflow;
|
||||
const off = math.cast(usize, atom.value) orelse return error.Overflow;
|
||||
const atom_size = math.cast(usize, atom.size) orelse return error.Overflow;
|
||||
try atom.getData(macho_file, code[off..][0..atom_size]);
|
||||
try atom.writeRelocs(macho_file, code[off..][0..atom_size], &relocs);
|
||||
@ -386,7 +386,7 @@ fn writeAtoms(macho_file: *MachO) !void {
|
||||
return error.FlushFailure;
|
||||
},
|
||||
};
|
||||
const file_offset = header.offset + atom.value - header.addr;
|
||||
const file_offset = header.offset + atom.value;
|
||||
const rels = relocs.getPtr(atom.out_n_sect).?;
|
||||
try atom.writeRelocs(macho_file, code, rels);
|
||||
try macho_file.base.file.?.pwriteAll(code, file_offset);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user