文件
Paze-C-CPP-Compiler/tools/pcc-asm.c
T
Paze AI 6a75c7f642 fix: pcc-asm 支持 -o 输出文件和符号过滤
- 新增 -o <file> 输出汇编到文件
- 支持过滤+输出组合 (pcc-asm app.exe callq -o calls.txt)
- 修复 cmd /c 引号处理(CreateProcess 不解析 > 重定向)
- 修复参数解析(-o 不再被当作过滤词)
2026-08-16 15:25:37 +08:00

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;
}