From 6a75c7f642a3fc7ea2fe8e90e5cb955c540ef536 Mon Sep 17 00:00:00 2001 From: Paze AI Date: Sun, 16 Aug 2026 15:25:37 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20pcc-asm=20=E6=94=AF=E6=8C=81=20-o=20?= =?UTF-8?q?=E8=BE=93=E5=87=BA=E6=96=87=E4=BB=B6=E5=92=8C=E7=AC=A6=E5=8F=B7?= =?UTF-8?q?=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 -o 输出汇编到文件 - 支持过滤+输出组合 (pcc-asm app.exe callq -o calls.txt) - 修复 cmd /c 引号处理(CreateProcess 不解析 > 重定向) - 修复参数解析(-o 不再被当作过滤词) --- bin/pcc-asm.exe | Bin 5632 -> 7168 bytes tools/pcc-asm.c | 126 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 84 insertions(+), 42 deletions(-) diff --git a/bin/pcc-asm.exe b/bin/pcc-asm.exe index 7c075cf029f70a4d9c76a734d4c415b5ae2e919d..efa0d336c313abab1b76c50c291624dd8b2ca3f8 100644 GIT binary patch literal 7168 zcmeHMZEPGz86GFOG`V7{ zPrGYl3y@MdE^H4=NJyv>g0?E+2Ly!L3ao-!yZ(Vw6lld)g(74mD%~|fG9MC2>-Kow znc2Ow@i_thL?tWlJ~QvU-}BDQ-g@A(Ut?PtW7}|7DvZqm>FO2F%^xQ*eBP8v{WoP)8OvI&xB8VD77fD7G(Ozz6 z>;chIk6y;C+WvppzU||Tt!yG2_svNkiaR+2zZ@|11?!(0Ps zQU}v29x$25any!630(Oss0gytc5sRhw=0Z-=^u1+CbqO<#ig&ylKT zJirw!OwTt!;QZM&B8MW8{@^wES?aD-D#Ewhq+C_|heOteawEphe-CjkAQ6ww$m;#@Vh-U~WObaZvK$2q;!~88Cc9se45b62TN8Gv3zR7J zBQ#8<7YwzPe)}HMi#j8J6D#6b63=CN&bKwt+*(svcsrSWgPnnUOYC6 z`B(2$D&^lv`~rkFOl6{QCSi;Lnwwq1}-mcZ7c2E&Z6D zufXYW^O&7p|QhE;bOD=T8}1^XN(MP^7bk5sgT%U2ikjuW}HjGjyg#=CRTXtqIi{Pz9eAh zI|4S2phrgVb1ASS1F69%82({)zkC~Cr@GgV5vv$_$u!3Q9>R!Hw`;No&x;@2pcXT{&+P>Em4)RW( z$$7fxnfbJ3a-9$M^>G-~-KnOgAx|GQdzv^`n!-;TlqJ6YTBF9YxPdPnbwoQI?u`3! z_$HNj`h*E5c@`P2Ba+wg0j1^wt8cnIJ;lALeA=-#6RR<&#B@8u$tZicEh99Q_b!Y37eUE#9|pI7*b!X<@oC_Ja|g2KNml-@Jec!zB5QrNBV zpu&*v|1I9UH(|JbJY!kNK$Z%g(6AiOL<3c92})kKEXR-(qd+gb7&3JFT9-HTo=J_Y zYbqHdUqC;V$~oy&cHAbpY{AXheikjcfN0#aBcf~Ooe7eTD5*z`f{*PME1Y;!u#wUW zg_J*4Aik90*uLvnS!oHI8d*uD(3qfxX;0)_hk{9^Mopi#4h(tdo0B==ZPpt1#@J(~ zYn#@+`&9<|TvPW=?DmG~d56ILu%7deIPS5WJ!+Xp(wid^u+NL-v^H zWfGHyS@3g?9k~vMYu8nsfvvn(_;-s!uJA#H;|iZv_#=f^bx_xwyYdXQGIkvI2<|c5 z>_f6m_=THfoA74*wj!Q3;B&aYgZnh@mNwZYr2o+nozTShVQLe88vjqA_Owy(k*l%4BN= zKmYmf=Raq%8Mx^|*2oxJf~Q(#Yz9apD&EI_-HGMp=k8t3_AEQNb|%z+aP8Kyw8L|D zcGT80JgHk&*5wI<+v65bTfBGk7M{tbj7W2HQ>!vP7-KAT4|%VRdDhWzQo{+1Ed{Sh z^1oOGY#};IFG)AZxM><#7?hLDPA2kFN&y6futk~yN6^o#W$bD}saKS-;rjVsq(6h* zxnt-?Tw~J3`V%MOMX^!tK~kVGI6{foDc#i>+eK?&FqDa%jHhlyQKX0zW4*-h#DiL~ zl{Bf1C}X8aP6`ea8w?>wwXPdcxl+eDPX1piuubzm*6#X@Iz;mZTC`&L(-n;Md9zv} z*3##_*zdj3@4a1l7j33_u_NFf(eg*wiXCT=24+&G@)87QLf{<=<0Wp9{j;D#OB%vU z8bgD1e#D{|J6ebx)siKx{6V8uY;YNQyxvw00#TNc>`tLknxQL&Hn%uk z`LSB91$_<-c+($&2c3%C;jL6f$-_1ki==@q3Rru|n0C>Nq#?a*l3x0}H|35{=gdN= zP$bKtvL|qX^UBj?1pBK}-$_$%`bH6n1lrPR`V7dbE~gCr_|c|9sFulXFfcO)={^tX z3Z!%=VX!82oiF5x1*{K~L)1)DvP4Iz0eV}nl+Y=x5#z#u;_FMuoL;3MkXf4g=jL;K zTSZHDQ~c;F1VJ&AyPDK%kXpd3yev6mfmmg?du$n$NgT6i}l54 zZRt_5k!XvbDeJ4sD|T!|cy%XDOYYaoAL3kw-yw<6oN8aK5aS}(*c#+fe?#;aZkg|{ zzIpgz1oLOl{GGx!wdaH%$Hg*^e5s0{Yv*^nlEm%c4b1z#o(+yKhnh$mAyKG>0o+}$ z7FeysJ8%{Q@hHS+&;nSm>ks(SWM@Jv67kF;EC#sLod> zDHp=u;Iph1n!gpW`a1&L09p|@D4K{D!lg4Qf^whtI)X)M)$u3)--u%zepZ^;ElunZ zuoCjPCKu&*^e607A$*rqxLYdZkD<_rlA^|y8*tZP=T%nI@EepV_$c5~gzYw1Lt#DK zW#P5L^1vF+TlzaixI|_!f08J|mjYIQCE&L+=#m-ilL{rNP(Fr2_YX3I>uK}zrB0Q? z0Zc2`NZzpGJx9C@9Mm#xJhYEy;vq z3z2O88^ca8)11h(XA`%k#xuEyF=?=Rx~FSsQ2jl>F>M;oP=EjSfuTg&8v2zQM0-r# z8oh)>+Ba;7tdCsr+mgM1TC!u@u{+?cL&d}bM!kDKVwOuL+jS?y+j%PO=#FD#5~jg* zKG@U4VMVv6nwqvb`l!*>#JMl5ey>pKJQxe~O_L|_yXALuGCF?S(5Tb7l#irM*RXkF ziaS%8MAjt7hQr&OCO^t9{})m=XIT7#Hs^vSwyw=t$JNZ*U*RVTzg8HA zZyGBVo~5u=VTZzN6>d~0wHO;x^Nhm0!iN^g{a^CPI1@?RjigKy6&Rr|AWWKB#{dzJ zr?ZLp$hegxZq80y?g+6RE1=OCrclc0rkN!$zOqoyv*jWY%)+tT~bstGYc(*5Yvx6GRx+MB2_$eDV0G;ZnR?4JU zwixa2er%HMbxMdZ-GkAvZ>{B!${a=pwgsV@JG-1Q(lKxL~JMR1sEAR_t CvT5A_ diff --git a/tools/pcc-asm.c b/tools/pcc-asm.c index 3e7c3a4..aa4008b 100644 --- a/tools/pcc-asm.c +++ b/tools/pcc-asm.c @@ -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 +#else +# include +# include #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; }