| ... | @@ -65,6 +65,7 @@ const Action = struct { | ... | @@ -65,6 +65,7 @@ const Action = struct { |
| 65 | fn match(act: Action, haystack: []const u8, global_vars: anytype) !bool { | 65 | fn match(act: Action, haystack: []const u8, global_vars: anytype) !bool { |
| 66 | assert(act.tag == .match); | 66 | assert(act.tag == .match); |
| 67 | | 67 | |
| | 68 | var candidate_var: ?struct { name: []const u8, value: u64 } = null; |
| 68 | var hay_it = mem.tokenize(u8, mem.trim(u8, haystack, " "), " "); | 69 | var hay_it = mem.tokenize(u8, mem.trim(u8, haystack, " "), " "); |
| 69 | var needle_it = mem.tokenize(u8, mem.trim(u8, act.phrase, " "), " "); | 70 | var needle_it = mem.tokenize(u8, mem.trim(u8, act.phrase, " "), " "); |
| 70 | | 71 | |
| ... | @@ -92,12 +93,19 @@ const Action = struct { | ... | @@ -92,12 +93,19 @@ const Action = struct { |
| 92 | const name = needle_tok[1..closing_brace]; | 93 | const name = needle_tok[1..closing_brace]; |
| 93 | if (name.len == 0) return error.MissingBraceValue; | 94 | if (name.len == 0) return error.MissingBraceValue; |
| 94 | const value = try std.fmt.parseInt(u64, hay_tok, 16); | 95 | const value = try std.fmt.parseInt(u64, hay_tok, 16); |
| 95 | try global_vars.putNoClobber(name, value); | 96 | candidate_var = .{ |
| | 97 | .name = name, |
| | 98 | .value = value, |
| | 99 | }; |
| 96 | } else { | 100 | } else { |
| 97 | if (!mem.eql(u8, hay_tok, needle_tok)) return false; | 101 | if (!mem.eql(u8, hay_tok, needle_tok)) return false; |
| 98 | } | 102 | } |
| 99 | } | 103 | } |
| 100 | | 104 | |
| | 105 | if (candidate_var) |v| { |
| | 106 | try global_vars.putNoClobber(v.name, v.value); |
| | 107 | } |
| | 108 | |
| 101 | return true; | 109 | return true; |
| 102 | } | 110 | } |
| 103 | | 111 | |
| ... | @@ -332,20 +340,43 @@ const MachODumper = struct { | ... | @@ -332,20 +340,43 @@ const MachODumper = struct { |
| 332 | var output = std.ArrayList(u8).init(gpa); | 340 | var output = std.ArrayList(u8).init(gpa); |
| 333 | const writer = output.writer(); | 341 | const writer = output.writer(); |
| 334 | | 342 | |
| 335 | var symtab_cmd: ?macho.symtab_command = null; | 343 | var load_commands = std.ArrayList(macho.LoadCommand).init(gpa); |
| | 344 | try load_commands.ensureTotalCapacity(hdr.ncmds); |
| | 345 | |
| | 346 | var sections = std.ArrayList(struct { seg: u16, sect: u16 }).init(gpa); |
| | 347 | var imports = std.ArrayList(u16).init(gpa); |
| | 348 | |
| | 349 | var symtab_cmd: ?u16 = null; |
| 336 | var i: u16 = 0; | 350 | var i: u16 = 0; |
| 337 | while (i < hdr.ncmds) : (i += 1) { | 351 | while (i < hdr.ncmds) : (i += 1) { |
| 338 | var cmd = try macho.LoadCommand.read(gpa, reader); | 352 | var cmd = try macho.LoadCommand.read(gpa, reader); |
| | 353 | load_commands.appendAssumeCapacity(cmd); |
| 339 | | 354 | |
| 340 | if (opts.dump_symtab and cmd.cmd() == .SYMTAB) { | 355 | switch (cmd.cmd()) { |
| 341 | symtab_cmd = cmd.symtab; | 356 | .SEGMENT_64 => { |
| | 357 | const seg = cmd.segment; |
| | 358 | for (seg.sections.items) |_, j| { |
| | 359 | try sections.append(.{ .seg = i, .sect = @intCast(u16, j) }); |
| | 360 | } |
| | 361 | }, |
| | 362 | .SYMTAB => { |
| | 363 | symtab_cmd = i; |
| | 364 | }, |
| | 365 | .LOAD_DYLIB, |
| | 366 | .LOAD_WEAK_DYLIB, |
| | 367 | .REEXPORT_DYLIB, |
| | 368 | => { |
| | 369 | try imports.append(i); |
| | 370 | }, |
| | 371 | else => {}, |
| 342 | } | 372 | } |
| 343 | | 373 | |
| 344 | try dumpLoadCommand(cmd, i, writer); | 374 | try dumpLoadCommand(cmd, i, writer); |
| 345 | try writer.writeByte('\n'); | 375 | try writer.writeByte('\n'); |
| 346 | } | 376 | } |
| 347 | | 377 | |
| 348 | if (symtab_cmd) |cmd| { | 378 | if (opts.dump_symtab) { |
| | 379 | const cmd = load_commands.items[symtab_cmd.?].symtab; |
| 349 | try writer.writeAll(symtab_label ++ "\n"); | 380 | try writer.writeAll(symtab_label ++ "\n"); |
| 350 | const strtab = bytes[cmd.stroff..][0..cmd.strsize]; | 381 | const strtab = bytes[cmd.stroff..][0..cmd.strsize]; |
| 351 | const raw_symtab = bytes[cmd.symoff..][0 .. cmd.nsyms * @sizeOf(macho.nlist_64)]; | 382 | const raw_symtab = bytes[cmd.symoff..][0 .. cmd.nsyms * @sizeOf(macho.nlist_64)]; |
| ... | @@ -354,7 +385,51 @@ const MachODumper = struct { | ... | @@ -354,7 +385,51 @@ const MachODumper = struct { |
| 354 | for (symtab) |sym| { | 385 | for (symtab) |sym| { |
| 355 | if (sym.stab()) continue; | 386 | if (sym.stab()) continue; |
| 356 | const sym_name = mem.sliceTo(@ptrCast([*:0]const u8, strtab.ptr + sym.n_strx), 0); | 387 | const sym_name = mem.sliceTo(@ptrCast([*:0]const u8, strtab.ptr + sym.n_strx), 0); |
| 357 | try writer.print("{s} {x}\n", .{ sym_name, sym.n_value }); | 388 | if (sym.sect()) { |
| | 389 | const map = sections.items[sym.n_sect - 1]; |
| | 390 | const seg = load_commands.items[map.seg].segment; |
| | 391 | const sect = seg.sections.items[map.sect]; |
| | 392 | try writer.print("{x} ({s},{s})", .{ |
| | 393 | sym.n_value, |
| | 394 | sect.segName(), |
| | 395 | sect.sectName(), |
| | 396 | }); |
| | 397 | if (sym.ext()) { |
| | 398 | try writer.writeAll(" external"); |
| | 399 | } |
| | 400 | try writer.print(" {s}\n", .{sym_name}); |
| | 401 | } else if (sym.undf()) { |
| | 402 | const ordinal = @divTrunc(@bitCast(i16, sym.n_desc), macho.N_SYMBOL_RESOLVER); |
| | 403 | const import_name = blk: { |
| | 404 | if (ordinal <= 0) { |
| | 405 | if (ordinal == macho.BIND_SPECIAL_DYLIB_SELF) |
| | 406 | break :blk "self import"; |
| | 407 | if (ordinal == macho.BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE) |
| | 408 | break :blk "main executable"; |
| | 409 | if (ordinal == macho.BIND_SPECIAL_DYLIB_FLAT_LOOKUP) |
| | 410 | break :blk "flat lookup"; |
| | 411 | unreachable; |
| | 412 | } |
| | 413 | const import_id = imports.items[@bitCast(u16, ordinal) - 1]; |
| | 414 | const import = load_commands.items[import_id].dylib; |
| | 415 | const full_path = mem.sliceTo(import.data, 0); |
| | 416 | const basename = fs.path.basename(full_path); |
| | 417 | assert(basename.len > 0); |
| | 418 | const ext = mem.lastIndexOfScalar(u8, basename, '.') orelse basename.len; |
| | 419 | break :blk basename[0..ext]; |
| | 420 | }; |
| | 421 | try writer.writeAll("(undefined)"); |
| | 422 | if (sym.weakRef()) { |
| | 423 | try writer.writeAll(" weak"); |
| | 424 | } |
| | 425 | if (sym.ext()) { |
| | 426 | try writer.writeAll(" external"); |
| | 427 | } |
| | 428 | try writer.print(" {s} (from {s})\n", .{ |
| | 429 | sym_name, |
| | 430 | import_name, |
| | 431 | }); |
| | 432 | } else unreachable; |
| 358 | } | 433 | } |
| 359 | } | 434 | } |
| 360 | | 435 | |