fix: pcc-asm 支持 -o 输出文件和符号过滤

- 新增 -o <file> 输出汇编到文件
- 支持过滤+输出组合 (pcc-asm app.exe callq -o calls.txt)
- 修复 cmd /c 引号处理(CreateProcess 不解析 > 重定向)
- 修复参数解析(-o 不再被当作过滤词)
这个提交包含在:
Paze AI
2026-08-16 15:25:37 +08:00
父节点 105c1f6f6a
当前提交 6a75c7f642
修改 2 个文件,包含 84 行新增42 行删除
二进制
查看文件
二进制文件未显示。
+84 -42
查看文件
@@ -5,8 +5,10 @@
* Uses llvm-objdump if available, else objdump.
*
* Usage:
* pcc-asm program.exe disassemble all code
* pcc-asm program.exe main disassemble, filter by symbol
* 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
*/
@@ -17,6 +19,9 @@
#ifdef _WIN32
# include <windows.h>
#else
# include <unistd.h>
# include <sys/wait.h>
#endif
static int file_exists(const char *f)
@@ -28,7 +33,6 @@ static int file_exists(const char *f)
static const char *find_objdump(void)
{
/* common locations, first match wins */
static const char *cands[] = {
"llvm-objdump.exe",
"objdump.exe",
@@ -43,67 +47,105 @@ static const char *find_objdump(void)
for (i = 0; cands[i]; i++)
if (file_exists(cands[i]))
return cands[i];
return "objdump"; /* hope it's in PATH */
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;
const char *file = NULL;
const char *filter = NULL;
char cmd[1024];
const char *outfile = NULL;
char cmd[2048];
int len;
int i;
const char *tmpfile = NULL;
if (argc < 2) {
/* 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 main disassemble, filter by symbol\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;
}
file = argv[1];
if (argc > 2)
filter = argv[2];
if (!file_exists(file)) {
fprintf(stderr, "pcc-asm: cannot open '%s'\n", file);
return 1;
}
#ifdef _WIN32
len = snprintf(cmd, sizeof cmd, "\"%s\" -d \"%s\"", objdump, file);
#else
len = snprintf(cmd, sizeof cmd, "%s -d \"%s\"", objdump, file);
#endif
if (filter) {
/* use objdump's symbol filter if supported, else grep-style */
len += snprintf(cmd + len, sizeof cmd - len, " | findstr /c:\"%s\"", filter);
/* 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);
}
#ifdef _WIN32
{
STARTUPINFOA si;
PROCESS_INFORMATION pi;
char *cmdline = (char*)malloc(strlen(cmd) + 1);
if (!cmdline) return 1;
strcpy(cmdline, cmd);
memset(&si, 0, sizeof si);
si.cb = sizeof si;
if (CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
free(cmdline);
}
#else
system(cmd);
#endif
(void)len;
return 0;
}