diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index c7150c2edc..8627a3917e 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -15,6 +15,7 @@ const Allocator = mem.Allocator; const Arch = std.Target.Cpu.Arch; const Relocation = reloc.Relocation; const Symbol = @import("Symbol.zig"); +const TextBlock = @import("Zld.zig").TextBlock; usingnamespace @import("commands.zig"); @@ -271,6 +272,7 @@ pub fn parse(self: *Object) !void { try self.parseSymtab(); try self.parseDataInCode(); try self.parseInitializers(); + try self.parseDummy(); } pub fn readLoadCommands(self: *Object, reader: anytype) !void { @@ -379,6 +381,110 @@ pub fn parseSections(self: *Object) !void { } } +fn cmpNlist(_: void, lhs: macho.nlist_64, rhs: macho.nlist_64) bool { + return lhs.n_value < rhs.n_value; +} + +fn filterSymsInSection(symbols: []macho.nlist_64, sect_id: u8) []macho.nlist_64 { + var start: usize = 0; + var end: usize = symbols.len; + + while (true) { + var change = false; + if (symbols[start].n_sect != sect_id) { + start += 1; + change = true; + } + if (symbols[end - 1].n_sect != sect_id) { + end -= 1; + change = true; + } + + if (start == end) break; + if (!change) break; + } + + return symbols[start..end]; +} + +pub fn parseDummy(self: *Object) !void { + const seg = self.load_commands.items[self.segment_cmd_index.?].Segment; + + log.warn("analysing {s}", .{self.name.?}); + + const dysymtab = self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab; + + var sorted_syms = std.ArrayList(macho.nlist_64).init(self.allocator); + defer sorted_syms.deinit(); + try sorted_syms.appendSlice(self.symtab.items[dysymtab.ilocalsym..dysymtab.iundefsym]); + + std.sort.sort(macho.nlist_64, sorted_syms.items, {}, cmpNlist); + + for (seg.sections.items) |sect, sect_id| { + log.warn("section {s},{s}", .{ parseName(§.segname), parseName(§.sectname) }); + // Read code + var code = try self.allocator.alloc(u8, @intCast(usize, sect.size)); + defer self.allocator.free(code); + _ = try self.file.?.preadAll(code, sect.offset); + + // Read and parse relocs + const 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 = try reloc.parse( + self.allocator, + self.arch.?, + code, + mem.bytesAsSlice(macho.relocation_info, raw_relocs), + ); + + if (self.header.?.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0) { + const syms = filterSymsInSection(sorted_syms.items, @intCast(u8, sect_id + 1)); + + var indices = std.ArrayList(u32).init(self.allocator); + defer indices.deinit(); + + var i: u32 = 0; + while (i < syms.len) : (i += 1) { + const curr = syms[i]; + try indices.append(i); + + const next: ?macho.nlist_64 = if (i + 1 < syms.len) + syms[i + 1] + else + null; + + if (next) |n| { + if (curr.n_value == n.n_value) { + continue; + } + } + + const start_addr = curr.n_value - sect.addr; + const end_addr = if (next) |n| n.n_value - sect.addr else sect.size; + const alignment = sect.@"align"; + + const tb_code = code[start_addr..end_addr]; + const size = tb_code.len; + + log.warn("TextBlock", .{}); + for (indices.items) |id| { + log.warn(" | symbol {s}", .{self.getString(syms[id].n_strx)}); + } + log.warn(" | start_addr = 0x{x}", .{start_addr}); + log.warn(" | end_addr = 0x{x}", .{end_addr}); + log.warn(" | size = {}", .{size}); + log.warn(" | alignment = 0x{x}", .{alignment}); + + indices.clearRetainingCapacity(); + } + } else { + return error.TODOOneLargeTextBlock; + } + } +} + pub fn parseInitializers(self: *Object) !void { const index = self.mod_init_func_section_index orelse return; const section = self.sections.items[index]; diff --git a/src/link/MachO/Zld.zig b/src/link/MachO/Zld.zig index f37bf7b696..152995c931 100644 --- a/src/link/MachO/Zld.zig +++ b/src/link/MachO/Zld.zig @@ -17,6 +17,7 @@ const Archive = @import("Archive.zig"); const CodeSignature = @import("CodeSignature.zig"); const Dylib = @import("Dylib.zig"); const Object = @import("Object.zig"); +const Relocation = reloc.Relocation; const StringTable = @import("StringTable.zig"); const Symbol = @import("Symbol.zig"); const Trie = @import("Trie.zig"); @@ -133,6 +134,16 @@ const TlvOffset = struct { } }; +pub const TextBlock = struct { + local_sym_index: ?u32 = null, + size: u64, + alignment: u32, + code: []u8, + relocs: []*Relocation, + segment_id: u16, + section_id: u16, +}; + /// Default path to dyld const DEFAULT_DYLD_PATH: [*:0]const u8 = "/usr/lib/dyld"; @@ -236,19 +247,6 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg try self.allocateSymbols(); try self.allocateTentativeSymbols(); try self.allocateProxyBindAddresses(); - - // log.warn("globals", .{}); - // for (self.globals.values()) |value| { - // log.warn(" | {s}: {}", .{ value.name, value.payload }); - // } - - // for (self.objects.items) |object| { - // log.warn("object {s}", .{object.name.?}); - // for (object.symbols.items) |sym| { - // log.warn(" | {s}: {}", .{ sym.name, sym.payload }); - // } - // } - try self.flush(); }