fix: pcc-asm 支持 -o 输出文件和符号过滤
- 新增 -o <file> 输出汇编到文件 - 支持过滤+输出组合 (pcc-asm app.exe callq -o calls.txt) - 修复 cmd /c 引号处理(CreateProcess 不解析 > 重定向) - 修复参数解析(-o 不再被当作过滤词)
这个提交包含在:
二进制
二进制文件未显示。
+81
-39
@@ -5,8 +5,10 @@
|
|||||||
* Uses llvm-objdump if available, else objdump.
|
* Uses llvm-objdump if available, else objdump.
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* pcc-asm program.exe disassemble all code
|
* 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 disassemble, filter by symbol
|
||||||
|
* pcc-asm program.exe main -o out.asm filter and save
|
||||||
*
|
*
|
||||||
* License: MIT
|
* License: MIT
|
||||||
*/
|
*/
|
||||||
@@ -17,6 +19,9 @@
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
|
#else
|
||||||
|
# include <unistd.h>
|
||||||
|
# include <sys/wait.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int file_exists(const char *f)
|
static int file_exists(const char *f)
|
||||||
@@ -28,7 +33,6 @@ static int file_exists(const char *f)
|
|||||||
|
|
||||||
static const char *find_objdump(void)
|
static const char *find_objdump(void)
|
||||||
{
|
{
|
||||||
/* common locations, first match wins */
|
|
||||||
static const char *cands[] = {
|
static const char *cands[] = {
|
||||||
"llvm-objdump.exe",
|
"llvm-objdump.exe",
|
||||||
"objdump.exe",
|
"objdump.exe",
|
||||||
@@ -43,67 +47,105 @@ static const char *find_objdump(void)
|
|||||||
for (i = 0; cands[i]; i++)
|
for (i = 0; cands[i]; i++)
|
||||||
if (file_exists(cands[i]))
|
if (file_exists(cands[i]))
|
||||||
return 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)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
const char *objdump = find_objdump();
|
const char *objdump = find_objdump();
|
||||||
const char *file;
|
const char *file = NULL;
|
||||||
const char *filter = NULL;
|
const char *filter = NULL;
|
||||||
char cmd[1024];
|
const char *outfile = NULL;
|
||||||
|
char cmd[2048];
|
||||||
int len;
|
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,
|
fprintf(stderr,
|
||||||
"pcc-asm - disassemble a PCC binary\n"
|
"pcc-asm - disassemble a PCC binary\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Usage:\n"
|
"Usage:\n"
|
||||||
" pcc-asm program.exe disassemble all code\n"
|
" pcc-asm program.exe disassemble all code\n"
|
||||||
" pcc-asm program.exe main disassemble, filter by symbol\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"
|
"\n"
|
||||||
"Uses %s\n", objdump);
|
"Uses %s\n", objdump);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
file = argv[1];
|
|
||||||
if (argc > 2)
|
|
||||||
filter = argv[2];
|
|
||||||
|
|
||||||
if (!file_exists(file)) {
|
if (!file_exists(file)) {
|
||||||
fprintf(stderr, "pcc-asm: cannot open '%s'\n", file);
|
fprintf(stderr, "pcc-asm: cannot open '%s'\n", file);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
/* 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);
|
len = snprintf(cmd, sizeof cmd, "\"%s\" -d \"%s\"", objdump, file);
|
||||||
#else
|
run_cmd(cmd);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
(void)len;
|
||||||
#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
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
在新工单中引用
屏蔽一个用户