| ... | ... | @@ -23,9 +23,23 @@ load_commands: std.ArrayListUnmanaged(LoadCommand) = .{}, |
| 23 | 23 | |
| 24 | 24 | symtab_cmd_index: ?u16 = null, |
| 25 | 25 | dysymtab_cmd_index: ?u16 = null, |
| 26 | id_cmd_index: ?u16 = null, |
| 27 | |
| 28 | id: ?Id = null, |
| 26 | 29 | |
| 27 | 30 | symbols: std.StringArrayHashMapUnmanaged(*Symbol) = .{}, |
| 28 | 31 | |
| 32 | pub const Id = struct { |
| 33 | name: []const u8, |
| 34 | timestamp: u32, |
| 35 | current_version: u32, |
| 36 | compatibility_version: u32, |
| 37 | |
| 38 | pub fn deinit(id: *Id, allocator: *Allocator) void { |
| 39 | allocator.free(id.name); |
| 40 | } |
| 41 | }; |
| 42 | |
| 29 | 43 | pub fn init(allocator: *Allocator) Dylib { |
| 30 | 44 | return .{ .allocator = allocator }; |
| 31 | 45 | } |
| ... | ... | @@ -45,6 +59,10 @@ pub fn deinit(self: *Dylib) void { |
| 45 | 59 | if (self.name) |name| { |
| 46 | 60 | self.allocator.free(name); |
| 47 | 61 | } |
| 62 | |
| 63 | if (self.id) |*id| { |
| 64 | id.deinit(self.allocator); |
| 65 | } |
| 48 | 66 | } |
| 49 | 67 | |
| 50 | 68 | pub fn closeFile(self: Dylib) void { |
| ... | ... | @@ -78,6 +96,7 @@ pub fn parse(self: *Dylib) !void { |
| 78 | 96 | } |
| 79 | 97 | |
| 80 | 98 | try self.readLoadCommands(reader); |
| 99 | try self.parseId(); |
| 81 | 100 | try self.parseSymbols(); |
| 82 | 101 | } |
| 83 | 102 | |
| ... | ... | @@ -94,6 +113,9 @@ pub fn readLoadCommands(self: *Dylib, reader: anytype) !void { |
| 94 | 113 | macho.LC_DYSYMTAB => { |
| 95 | 114 | self.dysymtab_cmd_index = i; |
| 96 | 115 | }, |
| 116 | macho.LC_ID_DYLIB => { |
| 117 | self.id_cmd_index = i; |
| 118 | }, |
| 97 | 119 | else => { |
| 98 | 120 | log.debug("Unknown load command detected: 0x{x}.", .{cmd.cmd()}); |
| 99 | 121 | }, |
| ... | ... | @@ -102,6 +124,32 @@ pub fn readLoadCommands(self: *Dylib, reader: anytype) !void { |
| 102 | 124 | } |
| 103 | 125 | } |
| 104 | 126 | |
| 127 | pub fn parseId(self: *Dylib) !void { |
| 128 | const index = self.id_cmd_index orelse { |
| 129 | log.debug("no LC_ID_DYLIB load command found; using hard-coded defaults...", .{}); |
| 130 | self.id = .{ |
| 131 | .name = try self.allocator.dupe(u8, self.name.?), |
| 132 | .timestamp = 2, |
| 133 | .current_version = 0, |
| 134 | .compatibility_version = 0, |
| 135 | }; |
| 136 | return; |
| 137 | }; |
| 138 | const id_cmd = self.load_commands.items[index].Dylib; |
| 139 | const dylib = id_cmd.inner.dylib; |
| 140 | |
| 141 | // TODO should we compare the name from the dylib's id with the user-specified one? |
| 142 | const dylib_name = @ptrCast([*:0]const u8, id_cmd.data[dylib.name - @sizeOf(macho.dylib_command) ..]); |
| 143 | const name = try self.allocator.dupe(u8, mem.spanZ(dylib_name)); |
| 144 | |
| 145 | self.id = .{ |
| 146 | .name = name, |
| 147 | .timestamp = dylib.timestamp, |
| 148 | .current_version = dylib.current_version, |
| 149 | .compatibility_version = dylib.compatibility_version, |
| 150 | }; |
| 151 | } |
| 152 | |
| 105 | 153 | pub fn parseSymbols(self: *Dylib) !void { |
| 106 | 154 | const index = self.symtab_cmd_index orelse return; |
| 107 | 155 | const symtab_cmd = self.load_commands.items[index].Symtab; |