我目前正在編譯一個購買的數據堆棧在C中。我使用自己的工具來編譯它,在後臺gcc中使用。我可以將標誌和參數傳遞給gcc,因爲我認爲合適。我想知道,從哪個文件中使用main()。也就是說,在項目中,哪個文件是起點。有沒有辦法告訴gcc生成一個文件列表,或類似的,因爲我不知道從哪個文件是main()被採取?謝謝。找到開始點,int main()
回答
您編譯調試符號的項目,可執行啓動gdb
,寫list main
,其次是「break
」或直接break main
。
'list main'甚至不顯示OP實際需要的文件名。 – 2012-07-30 11:07:12
謝謝你的回答。事實上,這並沒有顯示確切的文件,但顯示了使用的main的第一行,我可以對整個源代碼進行正常的文本搜索並找到插入位置。再次感謝您的答覆。 – 2012-07-30 11:25:50
如果你想查看行號和文件,你可以寫'break main',或者你在'list main'之後'break',等等。你不需要grep。 – alinsoar 2012-07-30 11:40:52
從哪裏main()
被稱爲是實現依賴 - 使用GCC,它很可能是在被稱爲crt0.o
或crt1.o
從它叫做/ usr/lib目錄存根對象文件。 (該文件包含操作系統相關的符號,當您的應用程序加載到內存中時,該符號將由內核自動調用。在Linux和Mac OS X上,這稱爲start
)。
您可以反彙編最終的可執行文件以找到起點。雖然你還沒有提供任何額外的信息來幫助你更多。我正在使用示例代碼來演示此過程。
#include <stdio.h>
int main() {
printf("hello world\n");
return 0;
}
現在對象main.o
有以下這
[[email protected] sf]# gcc -c main.c
[[email protected] sf]# nm main.o
0000000000000000 T main
U puts
你可以看到主未初始化。因爲它會在連接階段改變。現在鏈接後:
$gcc main.o
$nm a.out
U [email protected]@GLIBC_2.2.5
0000000000600874 A _edata
0000000000600888 A _end
00000000004005b8 T _fini
0000000000400390 T _init
00000000004003e0 T _start
000000000040040c t call_gmon_start
0000000000600878 b completed.6347
0000000000600870 W data_start
0000000000600880 b dtor_idx.6349
00000000004004a0 t frame_dummy
00000000004004c4 T main
您會看到main有一個地址。但它仍然不是最終的。因爲這個main將被C運行時動態調用。你可以看到誰做的U [email protected]@GLIBC_2.2.5
部分:
[[email protected] sf]# ldd a.out
linux-vdso.so.1 => (0x00007fff61de1000) /* the linux system call interface */
libc.so.6 => /lib64/libc.so.6 (0x0000003c96000000) /* libc runime , this will invoke your main*/
/lib64/ld-linux-x86-64.so.2 (0x0000003c95c00000) /* dynamic loader */
現在,您可以驗證這一點通過查看拆解:
00000000004003e0 <_start>:
..........
4003fd: 48 c7 c7 c4 04 40 00 mov rdi,0x4004c4 /* address of start of main */
400404: e8 bf ff ff ff call 4003c8 <[email protected]> /* this will set up the environment for main, like pushing argc and argv to stack */
...........
如果你不與你的來源,那麼你可以搜索請參閱libc_start_main
或main
或start
以查看您的可執行文件如何初始化並啓動main
。
現在,所有這些都是在鏈接完成時使用默認鏈接器腳本完成的。許多大型項目將使用自己的鏈接器腳本。如果您的項目具有自定義鏈接器腳本,則根據所使用的鏈接器腳本,查找起始點將會有所不同。有些項目不使用glibc's
運行時。在這種情況下,它仍然有可能通過黑客攻擊目標文件,庫檔案等來找到起點。
如果您的二進制文件是符號的stripped
,那麼您必須實際依賴您的彙編程序技能來查找它的起始位置。 (商業軟件供應商的一種慣例)。我認爲你沒有源代碼,那就是堆棧只與一些庫和一些頭文件定義一起分發。
但是,如果你有與你的來源,那麼它只是太瑣碎。只需grep
即可通過它。有些答案已經指出了。
您可以使用objdump -t
來列出目標文件中的符號。因此,假如你是在Linux上,並假設目標文件仍然在周圍的地方,你可以這樣做:
find -name '*.o' -print0 \
| xargs -0 objdump -t \
| awk '/\.o:/{f=$1} /\.text\.main/{print f, $6}'
這將打印對象的文件列表和它們所包含的main
引用。通常應該有一個從目標文件到源文件的簡單映射。如果有多個包含該符號的目標文件,則取決於實際鏈接到正在查看的二進制文件中的哪一個,因爲每個可執行二進制文件不能超過一個main
(除了某些真正具有異國情調的黑色魔法)。
在應用程序鏈接並且調試符號被剝離後,通常沒有指示特定函數來自哪個源文件。這個例外是包括函數名稱作爲字符串文字的文件,例如,使用宏__FILE__
。在剝離調試符號之前,您可以使用調試器來獲取該信息。如果包含調試符號,那就是。
- 1. 找到開始點做一個rebase -i
- 2. 如何查找「public static void main」或程序的開始?
- 3. int main()和void main()如何工作
- 4. int main()和int main(void)之間的區別?
- 5. 從其他包開始main(String args [])
- 6. 從int到main():: colors的轉換無效?
- 7. 用xpath開始找到webelement開頭
- 8. 轉換浮到int和離開零點
- 9. 查找開始與給定節點
- 10. int main(void)給出錯誤
- 11. 重新定義int main()C++
- 12. int main中的雙指針
- 13. 在C:主()和int main()的
- 14. 在一開始-V3沒有找到檢查點文件
- 15. XSL找到一個字符串,並從該點開始
- 16. 找不到符號睡眠(INT)printen(INT)
- 17. 程序執行是否始終從C中的main開始?
- 18. Java int數組增加了開始和結束點
- 19. 無法找到符號 - 方法fillArc(INT,INT,INT,INT,INT,INT)
- 20. 如何在VB.Net winforms應用程序中找到main()入口點?
- 21. 阿帕奇支點 - 「Main方法不是在課堂上找到」
- 22. DirectX 11.2錯誤:X3501:未找到'main'入口點
- 23. 找到一個int
- 24. 從ContentProvider類開始而不是從Main類開始的Android代碼
- 25. 找不到符號Integer.valueOf(int)
- 26. 找不到符號方法drawImage(SlidingBlockModel,int,int,int,int,<nulltype>)
- 27. 找到素數從2開始Haskell
- 28. 開始活動時未找到源
- 29. 找到原始開始日期到缺勤期間
- 30. 鑄造原始INT到數
應該只有一個包含'main'函數的文件,否則你會得到一個鏈接器錯誤。除非你告訴我們它是什麼工具,否則你的工具放在了我們無法知道的地方。 – 2012-07-30 10:40:02
順便說一句,這是一個非常糟糕的主意,試圖解決諸如此類的無證細節。 – 2012-07-30 10:40:39
爲什麼不是:grep -rni「main」。 ? – JohnTortugo 2013-06-22 21:56:04