| ... | ... | @@ -65,6 +65,7 @@ const Action = struct { |
| 65 | 65 | fn match(act: Action, haystack: []const u8, global_vars: anytype) !bool { |
| 66 | 66 | assert(act.tag == .match); |
| 67 | 67 | |
| 68 | var candidate_var: ?struct { name: []const u8, value: u64 } = null; |
| 68 | 69 | var hay_it = mem.tokenize(u8, mem.trim(u8, haystack, " "), " "); |
| 69 | 70 | var needle_it = mem.tokenize(u8, mem.trim(u8, act.phrase, " "), " "); |
| 70 | 71 | |
| ... | ... | @@ -92,12 +93,19 @@ const Action = struct { |
| 92 | 93 | const name = needle_tok[1..closing_brace]; |
| 93 | 94 | if (name.len == 0) return error.MissingBraceValue; |
| 94 | 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 | 100 | } else { |
| 97 | 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 | 109 | return true; |
| 102 | 110 | } |
| 103 | 111 | |
| ... | ... | @@ -332,20 +340,43 @@ const MachODumper = struct { |
| 332 | 340 | var output = std.ArrayList(u8).init(gpa); |
| 333 | 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 | 350 | var i: u16 = 0; |
| 337 | 351 | while (i < hdr.ncmds) : (i += 1) { |
| 338 | 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) { |
| 341 | | symtab_cmd = cmd.symtab; |
| 355 | switch (cmd.cmd()) { |
| 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 | 374 | try dumpLoadCommand(cmd, i, writer); |
| 345 | 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 | 380 | try writer.writeAll(symtab_label ++ "\n"); |
| 350 | 381 | const strtab = bytes[cmd.stroff..][0..cmd.strsize]; |
| 351 | 382 | const raw_symtab = bytes[cmd.symoff..][0 .. cmd.nsyms * @sizeOf(macho.nlist_64)]; |
| ... | ... | @@ -354,7 +385,51 @@ const MachODumper = struct { |
| 354 | 385 | for (symtab) |sym| { |
| 355 | 386 | if (sym.stab()) continue; |
| 356 | 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 | |