aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2021-04-01 18:18:04 +0200
committerJakub Konka <kubkon@jakubkonka.com>2021-04-13 10:56:03 +0200
commit1b5bceec910778ced3c03b885bddd31f1aac3842 (patch)
tree9cac2f009a1cb9efa315b7a3b86a75a1d7f86449 /src
parent04659f5b82cadb60112f00466ce1ce5b24b562f1 (diff)
downloadzig-1b5bceec910778ced3c03b885bddd31f1aac3842.tar.gz
zig-1b5bceec910778ced3c03b885bddd31f1aac3842.zip
zld: start work on reloc preprocessing
Diffstat (limited to 'src')
-rw-r--r--src/link/MachO/Object.zig57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig
index ac160288b5..61473a4c6b 100644
--- a/src/link/MachO/Object.zig
+++ b/src/link/MachO/Object.zig
@@ -97,6 +97,13 @@ pub fn parse(self: *Object) !void {
try self.readLoadCommands(reader);
if (self.symtab_cmd_index != null) try self.parseSymtab();
if (self.data_in_code_cmd_index != null) try self.readDataInCode();
+
+ {
+ const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
+ for (seg.sections.items) |_, sect_id| {
+ try self.parseRelocs(@intCast(u16, sect_id));
+ }
+ }
}
pub fn readLoadCommands(self: *Object, reader: anytype) !void {
@@ -163,6 +170,56 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void {
}
}
+pub fn parseRelocs(self: *Object, sect_id: u16) !void {
+ const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
+ const sect = seg.sections.items[sect_id];
+
+ if (sect.nreloc == 0) return;
+
+ var raw_relocs = try self.allocator.alloc(u8, @sizeOf(macho.relocation_info) * sect.nreloc);
+ defer self.allocator.free(raw_relocs);
+ _ = try self.file.?.preadAll(raw_relocs, sect.reloff);
+ const relocs = mem.bytesAsSlice(macho.relocation_info, raw_relocs);
+
+ for (relocs) |reloc| {
+ const is_addend = is_addend: {
+ switch (self.arch.?) {
+ .x86_64 => {
+ const rel_type = @intToEnum(macho.reloc_type_x86_64, reloc.r_type);
+ log.warn("{s}", .{rel_type});
+
+ break :is_addend false;
+ },
+ .aarch64 => {
+ const rel_type = @intToEnum(macho.reloc_type_arm64, reloc.r_type);
+ log.warn("{s}", .{rel_type});
+
+ break :is_addend rel_type == .ARM64_RELOC_ADDEND;
+ },
+ else => unreachable,
+ }
+ };
+
+ if (!is_addend) {
+ if (reloc.r_extern == 1) {
+ const sym = self.symtab.items[reloc.r_symbolnum];
+ const sym_name = self.getString(sym.inner.n_strx);
+ log.warn(" | symbol = {s}", .{sym_name});
+ } else {
+ const target_sect = seg.sections.items[reloc.r_symbolnum - 1];
+ log.warn(" | section = {s},{s}", .{
+ parseName(&target_sect.segname),
+ parseName(&target_sect.sectname),
+ });
+ }
+ }
+
+ log.warn(" | offset = 0x{x}", .{reloc.r_address});
+ log.warn(" | PC = {}", .{reloc.r_pcrel == 1});
+ log.warn(" | length = {}", .{reloc.r_length});
+ }
+}
+
pub fn parseSymtab(self: *Object) !void {
const symtab_cmd = self.load_commands.items[self.symtab_cmd_index.?].Symtab;