fix: pcc-asm 支持 -o 输出文件和符号过滤
- 新增 -o <file> 输出汇编到文件 - 支持过滤+输出组合 (pcc-asm app.exe callq -o calls.txt) - 修复 cmd /c 引号处理(CreateProcess 不解析 > 重定向) - 修复参数解析(-o 不再被当作过滤词)
这个提交包含在:
二进制
二进制文件未显示。
+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;
|
||||
}
|
||||
|
||||
在新工单中引用
屏蔽一个用户