是否有可能獲得用調試信息(gcc .. -g
)編譯的linux共享庫(.so
)的源代碼?感謝您的時間。使用調試符號獲取源
回答
棘手的問題。簡單的答案是否,你不能。
然而,如果你瞭解組裝您可以使用工具,如objdump的,GDB和其他人拆卸應用。並且從程序員可以重新編寫應用程序,從程序員熟練的。這並非易事,取決於目標應用程序的複雜程度而變得更加困難。
事實上,發行版本不是(或不應該)與-g
一起編譯。
否。調試信息只包含有關符號的信息,即變量和函數,但不包含代碼本身。
如果你的意思是反編譯,請看反編譯器(IDA Pro,例如);調試信息可以幫助很大,特別是如果您對完整源代碼不感興趣。
您可以使用調試符號來識別您感興趣的過程的起點。使用好的反向工程工具(如IDA或非常優秀的OllyDbg)可以爲這些部件獲得註釋反彙編。 OllyDbg和IDA能夠在一定程度上從反彙編生成C代碼。
有符號,但有幫助,但沒有魔藥
答案是:這取決於 - 不僅是編譯選項必要-g
,而且最終創建的可執行/共享libary可能無法在構建過程中去除。與-g
創建
目標文件做含有一種源代碼的 - 如果你對這樣的文件使用objdump -S
只是不作爲的源碼你喜歡它...
,它會穿插與源代碼行拆卸。
但顯示的是實際的編譯源 - 通過預處理器完成的任何操作,以及經過編譯器完成的任何內聯。
這意味着你可以從中得到令人驚訝的輸出;如果沒有其他,它的詳細程度可以看起來有點像Cobol的來源。首先:
#include <algorithm>
#include <functional>
int main(int argc, char **argv)
{
int array[] = { 1, 123, 1234, 12345, 123456 };
std::sort(array, array + sizeof(array)/sizeof(*array), std::less<int>());
return 0;
}
並通過g++ -O8 -g -o t t.C
,然後objdump -S t
運行它。這會給你的main()
類似於以下(你看,當然什麼取決於你的編譯器和/或庫)的輸出:
00000000004005e0 :
#include <algorithm>
#include <functional>
int main(int argc, char **argv)
{
4005e0: 41 57 push %r15
_ValueType<)
__glibcxx_requires_valid_range(__first, __last);
if (__first != __last)
{
std::__introsort_loop(__first, __last,
4005e2: ba 04 00 00 00 mov $0x4,%edx
4005e7: 41 56 push %r14
4005e9: 41 55 push %r13
4005eb: 41 54 push %r12
4005ed: 41 bc 04 00 00 00 mov $0x4,%r12d
4005f3: 55 push %rbp
4005f4: 53 push %rbx
4005f5: 48 83 ec 38 sub $0x38,%rsp
4005f9: 4c 8d 74 24 10 lea 0x10(%rsp),%r14
int array[] = { 1, 123, 1234, 12345, 123456 };
4005fe: c7 44 24 10 01 00 00 movl $0x1,0x10(%rsp)
400605: 00
400606: c7 44 24 14 7b 00 00 movl $0x7b,0x14(%rsp)
40060d: 00
40060e: c7 44 24 18 d2 04 00 movl $0x4d2,0x18(%rsp)
400615: 00
400616: c7 44 24 1c 39 30 00 movl $0x3039,0x1c(%rsp)
40061d: 00
40061e: 4d 8d 7e 14 lea 0x14(%r14),%r15
400622: 49 8d 6e 08 lea 0x8(%r14),%rbp
400626: 4c 89 f7 mov %r14,%rdi
400629: c7 44 24 20 40 e2 01 movl $0x1e240,0x20(%rsp)
400630: 00
400631: c6 04 24 00 movb $0x0,(%rsp)
400635: 4c 89 fe mov %r15,%rsi
400638: e8 73 01 00 00 callq 4007b0 <_ZSt16__introsort_loopIPilSt4lessIiEEvT_S3_T0_T1_>
40063d: eb 01 jmp 400640 <main+0x60>
40063f: 90 nop
if (__first == __last) return;
for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
{
typename iterator_traits<_RandomAccessIterator>::value_type
__val = *__i;
400640: 8b 5d fc mov -0x4(%rbp),%ebx
if (__comp(__val, *__first))
400643: 3b 5c 24 10 cmp 0x10(%rsp),%ebx
_ValueType>)
__glibcxx_requires_valid_range(__first, __last);
if (__first != __last)
{
std::__introsort_loop(__first, __last,
400647: 4b 8d 0c 34 lea (%r12,%r14,1),%rcx
for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
{
typename iterator_traits<_RandomAccessIterator>::value_type
__val = *__i;
if (__comp(__val, *__first))
40064b: 7c 53 jl 4006a0 <main+0xc0>
template<typename _Tp>
struct less : public binary_function<_Tp, _Tp, bool>
{
bool
operator()(const _Tp& __x, const _Tp& __y) const
{ return __x < __y; }
40064d: 8b 55 f8 mov -0x8(%rbp),%edx
{
std::copy_backward(__first, __i, __i + 1);
*__first = __val;
400650: 48 8d 45 f8 lea -0x8(%rbp),%rax
__unguarded_linear_insert(_RandomAccessIterator __last, _Tp __val,
_Compare __comp)
{
_RandomAccessIterator __next = __last;
--__next;
while (__comp(__val, *__next))
400654: 39 d3 cmp %edx,%ebx
400656: 7c 0e jl 400666 <main+0x86>
400658: eb 1c jmp 400676 <main+0x96>
40065a: eb 04 jmp 400660 <main+0x80>
40065c: 90 nop
40065d: 90 nop
40065e: 90 nop
40065f: 90 nop
400660: 48 89 c1 mov %rax,%rcx
400663: 48 89 f0 mov %rsi,%rax
{
*__last = *__next;
400666: 89 11 mov %edx,(%rcx)
400668: 8b 50 fc mov -0x4(%rax),%edx
__last = __next;
--__next;
40066b: 48 8d 70 fc lea -0x4(%rax),%rsi
__unguarded_linear_insert(_RandomAccessIterator __last, _Tp __val,
_Compare __comp)
{
_RandomAccessIterator __next = __last;
--__next;
while (__comp(__val, *__next))
40066f: 39 d3 cmp %edx,%ebx
400671: 7c ed jl 400660 <main+0x80>
400673: 48 89 c1 mov %rax,%rcx
{
*__last = *__next;
__last = __next;
--__next;
}
*__last = __val;
400676: 89 19 mov %ebx,(%rcx)
400678: 49 89 ed mov %rbp,%r13
40067b: 48 83 c5 04 add $0x4,%rbp
40067f: 49 83 c4 04 add $0x4,%r12
__insertion_sort(_RandomAccessIterator __first,
_RandomAccessIterator __last, _Compare __comp)
{
if (__first == __last) return;
for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
400683: 4d 39 ef cmp %r13,%r15
400686: 75 b8 jne 400640 <main+0x60>
std::sort(array, array + sizeof(array)/sizeof(*array), std::less<int>());
return 0;
}
400688: 48 83 c4 38 add $0x38,%rsp
40068c: 31 c0 xor %eax,%eax
40068e: 5b pop %rbx
40068f: 5d pop %rbp
400690: 41 5c pop %r12
400692: 41 5d pop %r13
400694: 41 5e pop %r14
400696: 41 5f pop %r15
400698: c3 retq
400699: eb 05 jmp 4006a0 <main+0xc0>
多大的幫助這個「源代碼」的存在將被保留爲在這一點上對讀者的練習;-)
+1這有幫助,謝謝:) – nc3b 2011-04-04 12:49:52
我嘗試使用_gfortran_而不是_gcc_,並且令人驚訝的是,所有的源代碼都在那裏,一行一行,甚至包括頭文件和註釋,所以可能取決於編譯器? – siritinga 2013-09-11 09:14:02
@siritinga:您在由gcc的C/C++編譯器部分創建的程序集中看到的「源代碼」是完整的_preprocessed_代碼。與「正常來源」('* .c' /'* .C'輸入文件)相比,這種龐大的容量可能會讓人分心。這就是爲什麼我一直在說「這對讀者有多大的幫助......」。 Fortran在預處理過程中做的這種修改較少,我並不感到驚訝,因爲它將更好的可讀/更接近編譯的輸入代碼嵌入到調試信息中。 – 2013-09-11 14:39:06
- 1. 在UNIX上獲取調試符號
- 2. 如何使用QMake文件獲取Valgrind的調試符號
- 3. 使用xperf獲取符號
- 4. 使用調試符號從源代碼編譯glibc
- 5. 嘗試使用gem調用方法時獲取符號轉換錯誤?
- 6. 使用Application Loader上傳調試符號
- 7. 調試solr 4.6源碼。獲取ClassNotFoundException:java.lang.ClassNotFoundException:solr.WhitespaceTokenizerFactory
- 8. 如何獲得U-Boot調試符號
- 9. 如何獲得LLVM調試符號
- 10. MSVC調試符號
- 11. Windows調試符號
- 12. JavaScript調試符號
- 13. Greasemonkey調試,獲取實際行號
- 14. 使用libvala-0.36調試VSCode需要調試符號?
- 15. 獲取GDB加載調試符號的難度
- 16. 獲取調試符號的模塊名稱
- 17. 如何在automake c項目中獲取調試符號?
- 18. 如何獲取Debian發行的程序的調試符號?
- 19. 從調試符號獲取堆棧偏移量
- 20. 嘗試使用EventKit時,獲取「未定義的符號」?
- 21. 獲取網站源代碼,獲取額外的符號,winsock
- 22. 如何獲取XPerfViewer以使用符號
- 23. 獲取調試錯誤使用C
- 24. 使用空格調試到NuGet符號包源文件夾失敗
- 25. VS 2012 C++:我可以使用源代替符號來調試嗎?
- 26. PHP獲取'+'符號
- 27. 調試符號和PE
- 28. 調試符號爲EPiServer 7
- 29. 調試符號未加載
- 30. LLVM庫的調試符號?
發佈版本應在編譯後_stripped_(它從所得到的二進制文件中刪除名稱,註釋和_debugging info_);這並不意味着'-g'將永遠不得不被刪除發佈版本,雖然。 – 2011-04-04 10:44:27
@karlphillip:如果我需要[C僞代碼](http://softwarerecs.stackexchange.com/q/26830/2341)會怎麼樣? – user2284570 2015-11-29 21:33:01