Fw: [問題] 用 GCC 編譯出來的程式想給華生博士偵錯

看板Programming作者 (軒摩斯)時間11年前 (2013/09/03 02:37), 編輯推噓6(609)
留言15則, 7人參與, 最新討論串1/2 (看更多)
※ [本文轉錄自 LinuxDev 看板 #1I96EHJt ] 請教前輩: 我在 linux 下安裝了 MinGW,可編譯出 Win32 可執行檔。 今有隻程式在 Win32 下運作卻無預警被關閉,想用 Dr. Watson 來進行捕捉, 得到 dump 檔與 log 檔,而 log 檔內寫著一行: *** ERROR: Module load completed but symbols could not be loaded for ... 我相信我的 symbols 都有安裝好路徑,但實在不解為何還是有這個訊息出現... 而反組譯發生錯誤的程式碼,都只有位址偏移,無從得知函數呼叫的情形, 由於光只拿著這一堆組合語言,實在無從 debug 起, 這個窘境有什麼方法解決或其他工具能更深入分析嗎? (不知道這個問題在這裡貼文是否適合,如有不當,敬請見諒!) 以下我寫了簡單的 crash 程式,測試一下由華生博士偵測後log 記錄之檔案, 節錄貼出來,讓大家看看我捕捉 gcc 程式的效果,並於後附上 crash 原始碼: *----> 執行執行緒識別碼 0xeac 的狀態傾印<----* eax=00000000 ebx=7ffd8000 ecx=00000000 edx=00000000 esi=00000000 edi=00000012 eip=00401329 esp=0022ff40 ebp=0022ff68 iopl=0 nv up ei pl zr na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 *** ERROR: Module load completed but symbols could not be loaded for D:\Temp\DrWaston\crash.exe 功能: crash 00401310 fc cld 00401311 fe00 inc byte ptr [eax] 00401313 0000 add [eax],al 00401315 7f51 jg crash+0x1368 (00401368) 00401317 8b45fc mov eax,[ebp-0x4] 0040131a 8b0d08404000 mov ecx,[crash+0x4008 (00404008)] 00401320 01c1 add ecx,eax 00401322 8b55f8 mov edx,[ebp-0x8] 00401325 b0ff mov al,0xff 00401327 20d0 and al,dl 錯誤 ->00401329 8801 mov [ecx],al ds:0023:00000000=?? 0040132b 8b45fc mov eax,[ebp-0x4] 0040132e 030508404000 add eax,[crash+0x4008 (00404008)] 00401334 0fbe00 movsx eax,byte ptr [eax] 00401337 89442408 mov [esp+0x8],eax 0040133b 8b45fc mov eax,[ebp-0x4] 0040133e 89442404 mov [esp+0x4],eax 00401342 c7042410304000 mov dword ptr [esp],0x403010 00401349 e85a050000 call crash+0x18a8 (004018a8) 0040134e 8b45fc mov eax,[ebp-0x4] 00401351 890424 mov [esp],eax 編譯指令: ~$ i386-mingw-gcc -g -o crash.exe crash.c 原始碼: << crash.c >> #include <stdio.h> #include <stdlib.h> char *g_lpCharacterPointer = NULL; void TestFunction(int iSize) { int i; if((g_lpCharacterPointer = (char *)malloc(sizeof(char) * iSize)) == NULL) { printf("Out of memory!\n"); return; } for(i = 0; i < iSize; i ++) { g_lpCharacterPointer[i] = (char)(i & 0xff); } free(g_lpCharacterPointer); } int main(void) { int i, iCounter = 0; for(i = 0; i < 255; i ++) { g_lpCharacterPointer[i] = (char)(iCounter & 0xff); printf("g_lpCharacterPointer[%d] == %d", i, g_lpCharacterPointer[i]); TestFunction(i); iCounter += i; } return 0; } -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 183.4.116.230 ※ 發信站: 批踢踢實業坊(ptt.cc) ※ 轉錄者: SeamusBerloz (183.4.116.230), 時間: 09/03/2013 10:37:08

09/03 11:32, , 1F
在 MinGW 下編譯時加上 -g 看看?
09/03 11:32, 1F

09/03 11:33, , 2F
(這是 GCC 加入除錯訊息的選項)
09/03 11:33, 2F

09/03 12:53, , 3F
謝謝 L 大!但我加過了,沒用耶,
09/03 12:53, 3F

09/03 12:53, , 4F
情況沒有改變...
09/03 12:53, 4F

09/03 13:24, , 5F
可能要研究一下用的檔案格式是哪種
09/03 13:24, 5F

09/03 13:25, , 6F
-g好像是預設dwarf格式 (我不熟...)
09/03 13:25, 6F

09/03 17:39, , 7F
try windbg
09/03 17:39, 7F

09/03 21:55, , 8F
不很熟 windbg,但一樣找不到 symbol
09/03 21:55, 8F

09/03 22:01, , 9F
還是說,symbols 要怎樣安裝才正確?
09/03 22:01, 9F

09/04 17:59, , 10F
到底是為什麼,不直接用gdb執行到當掉就好
09/04 17:59, 10F
說來話長,主要是因為 target 環境空間等不方便... 實驗室中實驗板上不曾發生退出,然而這次的 bug 十分詭異, 僅在工廠組裝線與機台設備共同運行時才出現,久久才累積一兩次, 並且不是可控制的重複或隨時出現,也更不是固定點出現退出情形, 機台設備十分昂貴,只能工廠擺放一台實際測試, 當然也都是靠工廠小朋友回報,才知道此當機退出的情形。 該 win32 平台實際是 XPe SP2,靠 SSD 當作儲存媒體。 需要的環境與程式經由 ghost 安裝到 SSD 後再安插到機台上。 主機板是訂製的工規板,沒有焊接 USB,連 PS/2 都沒有... 料想既然如此,就用捕捉的方式,進行錯誤訊息的最後保留, 於是 XPe 建構時要求多編入了 華生博士,嘗試最後一點希望, 然後拆回 SSD,拿到實驗室分析。 但若嘗試 gdb 當作 Win32 預設的 debugger, 自動帶起進行錯誤 dump,的確也是很好的點子, 我相信應該就是只差參數不知道怎樣下達, HKEY_LOCAL_MACHINE\ Software\Microsoft\Windows NT\CurrentVersion\AeDebug Debugger = %SystemRoot%//GNU//gdb -pid %ld ...? 只是至今還沒成功罷了... 故事寫到這裡,若再沒有簡易一點的辦法, 不排除直接採如 p 大的建議,拿出 EE 的 guts 暫換實驗板,上鍵盤,睡工廠...(T_T),用 gdb 等他當掉... ※ 編輯: SeamusBerloz 來自: 183.4.123.29 (09/04 21:32)

09/04 21:33, , 11F
這篇 MinGW FAQ 的 11. Debugging 不知如何?
09/04 21:33, 11F

09/04 21:34, , 12F
09/04 21:34, 12F
Dr.MinGW?!我還真沒見過這傢伙呢,感恩唷!趕緊研究一下先! ※ 編輯: SeamusBerloz 來自: 183.4.123.29 (09/04 21:47) 太棒了!直接出錯誤發生的行號給我 (有點廢話~呵呵!), 不過,這的確是目前最適合我的工具了!直接替代華生博士! 這麼好用的東西竟然我今天才知道,感謝!感謝!非常感謝~ <(_ _)> ※ 編輯: SeamusBerloz 來自: 183.4.123.29 (09/04 22:05) 在此給大家貼一下原述中的測試範例程式 crash.exe 的 dump 效果: crash.exe caused an Access Violation at location 00401397 in module crash.exe Writing to location 00000000. Registers: eax=00000000 ebx=7ffdf000 ecx=00000000 edx=00000000 esi=00000000 edi=00000012 eip=00401397 esp=0022ff50 ebp=0022ff78 iopl=0 nv up ei pl zr na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 Call stack: 00401397 crash.exe:00401397 main crash.c:32 int main( ) ... for(i = 0; i < 255; i ++) { > g_lpCharacterPointer[i] = (char)(iCounter & 0xff); printf("g_lpCharacterPointer[%d] == %d", i, g_lpCharacterPointer[i]); ... 004010B6 crash.exe:004010B6 00401148 crash.exe:00401148 7C817077 kernel32.dll:7C817077 RegisterWaitForInputIdle 只可惜我找到的這一版本,好像不能直接自動存檔, 不過效果相信已經非常好了。持續研究中... 以上版本是這裡取得的: http://code.google.com/p/jrfonseca/wiki/DrMingw ※ 編輯: SeamusBerloz 來自: 183.4.123.29 (09/04 22:28) Dr. MinGW 可說是 MinGW 愛用者的救星, 他甚至連 target 平台都不用安裝,也可以 dump 程式發生的錯誤, 只需要將隨附的 exchndl.dll 檔案,引用至程式中: 節錄一下我新的測試程式 crash_new.c: << crash_new.c >> #include <windows.h> ... int main(void) { ... LoadLibrary("./exchndl.dll"); ... } ... // 編譯指令: ~$ i386-mingw-gcc -g -fno-omit-frame-pointer -o crash.exe crash.c 然後將 exchndl.dll 與 mgwhelp.dll 放置在引入路徑中, 只要程式發生 crash,就會自動產生 crash.RPT 檔案, 這相當於華生博士的 log 檔案。 所以 target 有沒有設置 debugger 看來也無所謂了! 真是太棒了,再次感謝各位協助! ※ 編輯: SeamusBerloz 來自: 183.4.123.29 (09/04 23:05)

09/04 23:22, , 13F
看了一下介紹 Dr. Mingw 能解析 gcc 跟 vc
09/04 23:22, 13F

09/04 23:22, , 14F
兩者的符號,確實很好的工具
09/04 23:22, 14F

09/05 16:36, , 15F
Great
09/05 16:36, 15F
文章代碼(AID): #1I9KjLBy (Programming)
文章代碼(AID): #1I9KjLBy (Programming)