- 新增 -o <file> 输出汇编到文件 - 支持过滤+输出组合 (pcc-asm app.exe callq -o calls.txt) - 修复 cmd /c 引号处理(CreateProcess 不解析 > 重定向) - 修复参数解析(-o 不再被当作过滤词)
152 行
4.3 KiB
C
152 行
4.3 KiB
C
/*
|
|
* pcc-asm.c - disassemble a PCC-produced binary
|
|
*
|
|
* Shows the x86-64 assembly of a compiled program.
|
|
* Uses llvm-objdump if available, else objdump.
|
|
*
|
|
* Usage:
|
|
* pcc-asm program.exe disassemble all code (stdout)
|
|
* pcc-asm program.exe -o out.asm disassemble, save to file
|
|
* pcc-asm program.exe main disassemble, filter by symbol
|
|
* pcc-asm program.exe main -o out.asm filter and save
|
|
*
|
|
* License: MIT
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#ifdef _WIN32
|
|
# include <windows.h>
|
|
#else
|
|
# include <unistd.h>
|
|
# include <sys/wait.h>
|
|
#endif
|
|
|
|
static int file_exists(const char *f)
|
|
{
|
|
FILE *p = fopen(f, "rb");
|
|
if (p) { fclose(p); return 1; }
|
|
return 0;
|
|
}
|
|
|
|
static const char *find_objdump(void)
|
|
{
|
|
static const char *cands[] = {
|
|
"llvm-objdump.exe",
|
|
"objdump.exe",
|
|
"C:\\Program Files\\LLVM\\bin\\llvm-objdump.exe",
|
|
"C:\\Clang+LLVM-22.1.7\\bin\\llvm-objdump.exe",
|
|
"D:\\Clang+LLVM-22.1.7\\bin\\llvm-objdump.exe",
|
|
"/usr/bin/objdump",
|
|
"/usr/bin/llvm-objdump",
|
|
NULL
|
|
};
|
|
int i;
|
|
for (i = 0; cands[i]; i++)
|
|
if (file_exists(cands[i]))
|
|
return cands[i];
|
|
return "objdump";
|
|
}
|
|
|
|
/* run a command line; Windows uses cmd /c so that shell
|
|
redirection (>) and pipes (|) work */
|
|
static void run_cmd(const char *cmd)
|
|
{
|
|
#ifdef _WIN32
|
|
STARTUPINFOA si;
|
|
PROCESS_INFORMATION pi;
|
|
char *full = (char*)malloc(strlen(cmd) + 24);
|
|
if (!full) return;
|
|
/* cmd /c "cmd" - double quotes so embedded quotes survive */
|
|
strcpy(full, "cmd /c \"");
|
|
strcat(full, cmd);
|
|
strcat(full, "\"");
|
|
memset(&si, 0, sizeof si);
|
|
si.cb = sizeof si;
|
|
if (CreateProcessA(NULL, full, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
|
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
|
CloseHandle(pi.hProcess);
|
|
CloseHandle(pi.hThread);
|
|
}
|
|
free(full);
|
|
#else
|
|
system(cmd);
|
|
#endif
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
const char *objdump = find_objdump();
|
|
const char *file = NULL;
|
|
const char *filter = NULL;
|
|
const char *outfile = NULL;
|
|
char cmd[2048];
|
|
int len;
|
|
int i;
|
|
const char *tmpfile = NULL;
|
|
|
|
/* parse args: file [filter] [-o outfile] */
|
|
for (i = 1; i < argc; i++) {
|
|
if (strcmp(argv[i], "-o") == 0 && i + 1 < argc) {
|
|
outfile = argv[++i];
|
|
} else if (!file) {
|
|
file = argv[i];
|
|
} else if (!filter) {
|
|
filter = argv[i];
|
|
} else {
|
|
fprintf(stderr, "pcc-asm: too many arguments\n");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
if (!file) {
|
|
fprintf(stderr,
|
|
"pcc-asm - disassemble a PCC binary\n"
|
|
"\n"
|
|
"Usage:\n"
|
|
" pcc-asm program.exe disassemble all code\n"
|
|
" pcc-asm program.exe -o out.asm save to file\n"
|
|
" pcc-asm program.exe main filter by symbol\n"
|
|
" pcc-asm program.exe main -o out.asm filter and save\n"
|
|
"\n"
|
|
"Uses %s\n", objdump);
|
|
return 1;
|
|
}
|
|
|
|
if (!file_exists(file)) {
|
|
fprintf(stderr, "pcc-asm: cannot open '%s'\n", file);
|
|
return 1;
|
|
}
|
|
|
|
/* Step 1: disassemble.
|
|
If filtering, first write full output to a temp file,
|
|
then filter that file. */
|
|
if (filter && outfile) {
|
|
/* need a temp file for the full listing */
|
|
static char tmp[L_tmpnam + 1];
|
|
tmpfile = tmpnam(tmp);
|
|
if (!tmpfile) { fprintf(stderr, "pcc-asm: tmpnam failed\n"); return 1; }
|
|
len = snprintf(cmd, sizeof cmd, "\"%s\" -d \"%s\" > \"%s\"", objdump, file, tmpfile);
|
|
run_cmd(cmd);
|
|
/* then filter temp -> outfile */
|
|
len = snprintf(cmd, sizeof cmd, "findstr /c:\"%s\" \"%s\" > \"%s\"", filter, tmpfile, outfile);
|
|
run_cmd(cmd);
|
|
remove(tmpfile);
|
|
printf("pcc-asm: wrote %s\n", outfile);
|
|
} else if (filter) {
|
|
len = snprintf(cmd, sizeof cmd, "\"%s\" -d \"%s\" | findstr /c:\"%s\"", objdump, file, filter);
|
|
run_cmd(cmd);
|
|
} else if (outfile) {
|
|
len = snprintf(cmd, sizeof cmd, "\"%s\" -d \"%s\" > \"%s\"", objdump, file, outfile);
|
|
run_cmd(cmd);
|
|
printf("pcc-asm: wrote %s\n", outfile);
|
|
} else {
|
|
len = snprintf(cmd, sizeof cmd, "\"%s\" -d \"%s\"", objdump, file);
|
|
run_cmd(cmd);
|
|
}
|
|
(void)len;
|
|
return 0;
|
|
}
|