天天看點

linux可執行檔案的内容分析工具nm objdump readelf ar ldd(轉)

http://www.ibm.com/developerworks/cn/aix/library/au-unixtools.html

UNIX(R) 系統中運作的程式遵守一種稱為目标檔案格式的精心設計。了解更多關于目标檔案格式的内容,以及可以用來研究系統中目标檔案的工具。

計算機程式設計的最新技術将一種特殊的人性與一組特殊的工具結合在一起,用以生産出對其他人非常有幫助的一種神奇的産品,即軟體。計算機程式員是一群注重細節的人,他們可以處理計算機中各種各樣的困難。計算機的要求非常苛刻,并且不能容忍其中存在任何的偏差。毫無疑問,無論您的個性如何以及在工作中使用了何種輔助工具,計算機程式的編寫都是非常困難的。

在 UNIX® 和 Linux® 中,任何事物都是檔案。您可以認為,UNIX 和 Linux 程式設計實際上是編寫處理各種檔案的代碼。系統由許多類型的檔案組成,但目标檔案具有一種特殊的設計,提供了靈活和多樣的用途。

目标檔案是包含帶有附加位址和值的助記符号的路線圖。這些符号可以用來對各種代碼段和資料段進行命名,包括經過初始化的和未初始化的。它們也可以用來定位嵌入的調試資訊,就像語義 Web,非常适合由程式進行閱讀。

行業工具

計算機程式設計中使用的工具包括代碼編輯器,如 vi 或 Emacs,您可以使用這些工具輸入和編輯希望計算機在完成所需任務時執行的指令,以及編譯器和連接配接器,它們可以生成真正實作這些目标的機器代碼。

進階的工具,稱為內建調試環境 (IDE),它以統一的外觀內建了不同工具的功能。IDE 使得編輯器、編譯器、連接配接器和調試器之間的界限變得很模糊。是以,為了更深入地研究和了解系統,在使用內建的套件之前,最好先單獨地使用這些工具。(注意:IDE 也通常被稱為內建開發環境。)

編譯器可以将您在代碼編輯器中建立的文本轉換為目标檔案。最初,目标檔案被稱為代碼的中間表示形式,因為它用作連接配接編輯器(即連接配接器)的輸入,而連接配接編輯器最終完成整個任務并生成可執行的程式作為輸出。

從代碼到可執行代碼的轉換過程經過了良好的定義并實作了自動化,而目标檔案是這個鍊中有機的連接配接性環節。在這個轉換過程中,目标檔案作為連接配接編輯器所使用的映象,使得它們能夠解析各種符号并将不同的代碼和資料段連接配接在一起形成統一的整體。

曆史

計算機程式設計領域中存在許多著名的目标檔案格式。DOS 系列包括 COM、OBJ 和 EXE 格式。UNIX 和 Linux 使用 a.out、COFF 和 ELF。Microsoft® Windows® 使用可移植的執行檔案 (PE) 格式,而 Macintosh 使用 PEF、Mach-O 和其他檔案格式。

最初,各種類型的計算機具有自己獨特的目标檔案格式,但随着 UNIX 和其他在不同硬體平台上提供可移植性的作業系統的出現,一些常用的檔案格式上升為通用的标準。其中包括 a.out、COFF 和 ELF 格式。

要了解目标檔案,需要一組可以讀取目标檔案中不同部分并以更易于讀取的格式顯示這些内容的工具。本文将讨論這些工具中比較重要的方面。但首先,您必須建立一個工作台,并在其中建立一個研究對象。

工作台

啟動一個 xterm 會話,讓我們先建立一個空白的工作台,并開始對目标檔案進行研究。下面的指令建立了一個目錄,可以将目标檔案放到該目錄中進行研究:

cdmkdir srccd srcmkdir hwcd hw      

然後,使用您最喜歡的代碼編輯器,在 $HOME/src/hw 目錄中輸入清單 1 中的程式,并命名為 hw.c。

清單 1. hw.c 程式

#include <stdio.h>int main(void){  printf("Hello World!/n");  return 0;}      

要使用 UNIX 工具庫中提供的各種工具,可以将這個簡單的“Hello World”程式作為研究的對象。您将學習建構和檢視目标檔案的輸出,而不是使用任何快捷方法直接建立可執行檔案(的确有許多這樣的快捷方法)。

檔案格式

C

編譯器的正常輸出是用于您所指定的目标處理器的彙編代碼。彙編代碼是彙編器的輸入,在預設情況下,彙編器将生成所有目标檔案的祖先,即 a.out 檔案。這個名稱本身表示彙編輸出 (Assembler Output)。要建立 a.out 檔案,可以在 xterm 視窗中輸入下面的指令:

cc hw.c      

注意:如果出現了任何錯誤或者沒有建立 a.out 檔案,那麼您可能需要檢查自己的系統或源檔案 (hw.c),以找出其中的錯誤。還需要檢查是否已将 cc 定義為運作您的

C/C++

編譯器。

最新的

C

編譯器将編譯和彙編步驟組合成一個步驟。您可以指定不同開關選項以檢視

C

編譯器的彙編輸出。通過輸入下面的指令,您可以看到

C

編譯器的彙編輸出:

cc -S hw.c      

這個指令生成了一個新的檔案 hw.s,其中包含您通常無法看到的彙編輸入文本,因為編譯器在預設情況下将生成 a.out 檔案。正如所預期的,UNIX 彙程式設計式可以對這種輸入檔案進行彙編,以生成 a.out 檔案。

UNIX 特定的工具

假定編譯過程一切順利,那麼在該目錄中就有了一個 a.out 檔案,下面讓我們來對其進行研究。有許多可用于研究目标檔案的有價值的工具,下面便是其中一組:

  • nm:列出目标檔案中的符号。
  • objdump:顯示目标檔案中的詳細資訊。
  • readelf:顯示關于 ELF 目标檔案的資訊。

       具體的readelf指令可以檢視本部落格的其他文章

清單中的第一個工具是 nm,它可以列出目标檔案中的符号。如果您輸入

nm

指令,您将注意到在預設情況下,它會尋找一個名為 a.out 的檔案。如果沒有找到該檔案,這個工具會給出相應的提示。然而,如果該工具找到了編譯器建立的 a.out 檔案,它将顯示類似清單 2 的清單。

清單 2. nm 指令的輸出

08049594 A __bss_start080482e4 t call_gmon_start08049594 b completed.446308049498 d __CTOR_END__08049494 d __CTOR_LIST__08049588 D __data_start08049588 W data_start0804842c t __do_global_ctors_aux0804830c t __do_global_dtors_aux0804958c D __dso_handle080494a0 d __DTOR_END__0804949c d __DTOR_LIST__080494a8 d _DYNAMIC08049594 A _edata08049598 A _end08048458 T _fini08049494 a __fini_array_end08049494 a __fini_array_start08048478 R _fp_hw0804833b t frame_dummy08048490 r __FRAME_END__08049574 d _GLOBAL_OFFSET_TABLE_         w __gmon_start__08048308 T __i686.get_pc_thunk.bx08048278 T _init08049494 a __init_array_end08049494 a __init_array_start0804847c R _IO_stdin_used080494a4 d __JCR_END__080494a4 d __JCR_LIST__         w _Jv_RegisterClasses080483e1 T __libc_csu_fini08048390 T __libc_csu_init         U [email protected]@GLIBC_2.008048360 T main08049590 d p.4462         U [email protected]@GLIBC_2.0080482c0 T _start      

這些包含可執行代碼的段稱為正文段。同樣地,資料段包含了不可執行的資訊或資料。另一種類型的段,稱為 BSS 段,它包含以符号資料開頭的塊。

對于

nm

指令列出的每個符号,它們的值使用十六進制來表示(預設行為),并且在該符号前面加上了一個表示符号類型的編碼字元。常見的各種編碼包括:A 表示絕對 (absolute),這意味着不能将該值更改為其他的連接配接;B 表示 BSS 段中的符号;而 C 表示引用未初始化的資料的一般符号。

可以将目标檔案中所包含的不同的部分劃分為段。段可以包含可執行代碼、符号名稱、初始資料值和許多其他類型的資料。有關這些類型的資料的詳細資訊,可以閱讀 UNIX 中

nm

的 man 頁面,其中按照該指令輸出中的字元編碼分别對每種類型進行了描述。

細節,細節…

在目标檔案階段,即使是一個簡單的 Hello World 程式,其中也包含了大量的細節資訊。nm 程式可用于列舉符号及其類型和值,但是,要更仔細地研究目标檔案中這些命名段的内容,需要使用功能更強大的工具。

其中兩種功能強大的工具是 objdump 和 readelf 程式。通過輸入下面的指令,您可以看到目标檔案中包含可執行代碼的每個段的彙編清單。對于這麼一個小的程式,編譯器生成了這麼多的代碼,真的很令人驚異!

objdump -d a.out      

這個指令生成的輸出如清單 3 所示。每個可執行代碼段将在需要特定的事件時執行,這些事件包括庫的初始化和該程式本身主入口點。

清單 3. objdump 指令的輸出

a.out:     file format elf32-i386Disassembly of section .init:08048278 <_init>: 8048278:       55                      push   %ebp 8048279:       89 e5                   mov    %esp,%ebp 804827b:       83 ec 08                sub    $0x8,%esp 804827e:       e8 61 00 00 00          call   80482e4 <call_gmon_start> 8048283:       e8 b3 00 00 00          call   804833b <frame_dummy> 8048288:       e8 9f 01 00 00          call   804842c <__do_global_ctors_aux> 804828d:       c9                      leave 804828e:       c3                      retDisassembly of section .plt:08048290 <[email protected]>: 8048290:       ff 35 78 95 04 08       pushl  0x8049578 8048296:       ff 25 7c 95 04 08       jmp    *0x804957c 804829c:       00 00                   add    %al,(%eax)        ...080482a0 <[email protected]>: 80482a0:       ff 25 80 95 04 08       jmp    *0x8049580 80482a6:       68 00 00 00 00          push   $0x0 80482ab:       e9 e0 ff ff ff          jmp    8048290 <_init+0x18>080482b0 <[email protected]>: 80482b0:       ff 25 84 95 04 08       jmp    *0x8049584 80482b6:       68 08 00 00 00          push   $0x8 80482bb:       e9 d0 ff ff ff          jmp    8048290 <_init+0x18>Disassembly of section .text:080482c0 <_start>: 80482c0:       31 ed                   xor    %ebp,%ebp 80482c2:       5e                      pop    %esi 80482c3:       89 e1                   mov    %esp,%ecx 80482c5:       83 e4 f0                and    $0xfffffff0,%esp 80482c8:       50                      push   %eax 80482c9:       54                      push   %esp 80482ca:       52                      push   %edx 80482cb:       68 e1 83 04 08          push   $0x80483e1 80482d0:       68 90 83 04 08          push   $0x8048390 80482d5:       51                      push   %ecx 80482d6:       56                      push   %esi 80482d7:       68 60 83 04 08          push   $0x8048360 80482dc:       e8 cf ff ff ff          call   80482b0 <[email protected]> 80482e1:       f4                      hlt 80482e2:       90                      nop 80482e3:       90                      nop080482e4 <call_gmon_start>: 80482e4:       55                      push   %ebp 80482e5:       89 e5                   mov    %esp,%ebp 80482e7:       53                      push   %ebx 80482e8:       e8 1b 00 00 00          call   8048308 <__i686.get_pc_thunk.bx> 80482ed:       81 c3 87 12 00 00       add    $0x1287,%ebx 80482f3:       83 ec 04                sub    $0x4,%esp 80482f6:       8b 83 fc ff ff ff       mov    0xfffffffc(%ebx),%eax 80482fc:       85 c0                   test   %eax,%eax 80482fe:       74 02                   je     8048302 <call_gmon_start+0x1e> 8048300:       ff d0                   call   *%eax 8048302:       83 c4 04                add    $0x4,%esp 8048305:       5b                      pop    %ebx 8048306:       5d                      pop    %ebp 8048307:       c3                      ret08048308 <__i686.get_pc_thunk.bx>: 8048308:       8b 1c 24                mov    (%esp),%ebx 804830b:       c3                      ret0804830c <__do_global_dtors_aux>: 804830c:       55                      push   %ebp 804830d:       89 e5                   mov    %esp,%ebp 804830f:       83 ec 08                sub    $0x8,%esp 8048312:       80 3d 94 95 04 08 00    cmpb   $0x0,0x8049594 8048319:       74 0c                   je     8048327 <__do_global_dtors_aux+0x1b> 804831b:       eb 1c                   jmp    8048339 <__do_global_dtors_aux+0x2d> 804831d:       83 c0 04                add    $0x4,%eax 8048320:       a3 90 95 04 08          mov    %eax,0x8049590 8048325:       ff d2                   call   *%edx 8048327:       a1 90 95 04 08          mov    0x8049590,%eax 804832c:       8b 10                   mov    (%eax),%edx 804832e:       85 d2                   test   %edx,%edx 8048330:       75 eb                   jne    804831d <__do_global_dtors_aux+0x11> 8048332:       c6 05 94 95 04 08 01    movb   $0x1,0x8049594 8048339:       c9                      leave 804833a:       c3                      ret0804833b <frame_dummy>: 804833b:       55                      push   %ebp 804833c:       89 e5                   mov    %esp,%ebp 804833e:       83 ec 08                sub    $0x8,%esp 8048341:       a1 a4 94 04 08          mov    0x80494a4,%eax 8048346:       85 c0                   test   %eax,%eax 8048348:       74 12                   je     804835c <frame_dummy+0x21> 804834a:       b8 00 00 00 00          mov    $0x0,%eax 804834f:       85 c0                   test   %eax,%eax 8048351:       74 09                   je     804835c <frame_dummy+0x21> 8048353:       c7 04 24 a4 94 04 08    movl   $0x80494a4,(%esp) 804835a:       ff d0                   call   *%eax 804835c:       c9                      leave 804835d:       c3                      ret 804835e:       90                      nop 804835f:       90                      nop08048360 <main>: 8048360:       55                      push   %ebp 8048361:       89 e5                   mov    %esp,%ebp 8048363:       83 ec 08                sub    $0x8,%esp 8048366:       83 e4 f0                and    $0xfffffff0,%esp 8048369:       b8 00 00 00 00          mov    $0x0,%eax 804836e:       83 c0 0f                add    $0xf,%eax 8048371:       83 c0 0f                add    $0xf,%eax 8048374:       c1 e8 04                shr    $0x4,%eax 8048377:       c1 e0 04                shl    $0x4,%eax 804837a:       29 c4                   sub    %eax,%esp 804837c:       c7 04 24 80 84 04 08    movl   $0x8048480,(%esp) 8048383:       e8 18 ff ff ff          call   80482a0 <[email protected]> 8048388:       b8 00 00 00 00          mov    $0x0,%eax 804838d:       c9                      leave 804838e:       c3                      ret 804838f:       90                      nop08048390 <__libc_csu_init>: 8048390:       55                      push   %ebp 8048391:       89 e5                   mov    %esp,%ebp 8048393:       57                      push   %edi 8048394:       56                      push   %esi 8048395:       31 f6                   xor    %esi,%esi 8048397:       53                      push   %ebx 8048398:       e8 6b ff ff ff          call   8048308 <__i686.get_pc_thunk.bx> 804839d:       81 c3 d7 11 00 00       add    $0x11d7,%ebx 80483a3:       83 ec 0c                sub    $0xc,%esp 80483a6:       e8 cd fe ff ff          call   8048278 <_init> 80483ab:       8d 83 20 ff ff ff       lea    0xffffff20(%ebx),%eax 80483b1:       8d 93 20 ff ff ff       lea    0xffffff20(%ebx),%edx 80483b7:       89 45 f0                mov    %eax,0xfffffff0(%ebp) 80483ba:       29 d0                   sub    %edx,%eax 80483bc:       c1 f8 02                sar    $0x2,%eax 80483bf:       39 c6                   cmp    %eax,%esi 80483c1:       73 16                   jae    80483d9 <__libc_csu_init+0x49> 80483c3:       89 d7                   mov    %edx,%edi 80483c5:       ff 14 b2                call   *(%edx,%esi,4) 80483c8:       8b 45 f0                mov    0xfffffff0(%ebp),%eax 80483cb:       83 c6 01                add    $0x1,%esi 80483ce:       29 f8                   sub    %edi,%eax 80483d0:       89 fa                   mov    %edi,%edx 80483d2:       c1 f8 02                sar    $0x2,%eax 80483d5:       39 c6                   cmp    %eax,%esi 80483d7:       72 ec                   jb     80483c5 <__libc_csu_init+0x35> 80483d9:       83 c4 0c                add    $0xc,%esp 80483dc:       5b                      pop    %ebx 80483dd:       5e                      pop    %esi 80483de:       5f                      pop    %edi 80483df:       5d                      pop    %ebp 80483e0:       c3                      ret080483e1 <__libc_csu_fini>: 80483e1:       55                      push   %ebp 80483e2:       89 e5                   mov    %esp,%ebp 80483e4:       83 ec 18                sub    $0x18,%esp 80483e7:       89 5d f4                mov    %ebx,0xfffffff4(%ebp) 80483ea:       e8 19 ff ff ff          call   8048308 <__i686.get_pc_thunk.bx> 80483ef:       81 c3 85 11 00 00       add    $0x1185,%ebx 80483f5:       89 75 f8                mov    %esi,0xfffffff8(%ebp) 80483f8:       89 7d fc                mov    %edi,0xfffffffc(%ebp) 80483fb:       8d b3 20 ff ff ff       lea    0xffffff20(%ebx),%esi 8048401:       8d bb 20 ff ff ff       lea    0xffffff20(%ebx),%edi 8048407:       29 fe                   sub    %edi,%esi 8048409:       c1 fe 02                sar    $0x2,%esi 804840c:       eb 03                   jmp    8048411 <__libc_csu_fini+0x30> 804840e:       ff 14 b7                call   *(%edi,%esi,4) 8048411:       83 ee 01                sub    $0x1,%esi 8048414:       83 fe ff                cmp    $0xffffffff,%esi 8048417:       75 f5                   jne    804840e <__libc_csu_fini+0x2d> 8048419:       e8 3a 00 00 00          call   8048458 <_fini> 804841e:       8b 5d f4                mov    0xfffffff4(%ebp),%ebx 8048421:       8b 75 f8                mov    0xfffffff8(%ebp),%esi 8048424:       8b 7d fc                mov    0xfffffffc(%ebp),%edi 8048427:       89 ec                   mov    %ebp,%esp 8048429:       5d                      pop    %ebp 804842a:       c3                      ret 804842b:       90                      nop0804842c <__do_global_ctors_aux>: 804842c:       55                      push   %ebp 804842d:       89 e5                   mov    %esp,%ebp 804842f:       53                      push   %ebx 8048430:       83 ec 04                sub    $0x4,%esp 8048433:       a1 94 94 04 08          mov    0x8049494,%eax 8048438:       83 f8 ff                cmp    $0xffffffff,%eax 804843b:       74 12                   je     804844f <__do_global_ctors_aux+0x23> 804843d:       bb 94 94 04 08          mov    $0x8049494,%ebx 8048442:       ff d0                   call   *%eax 8048444:       8b 43 fc                mov    0xfffffffc(%ebx),%eax 8048447:       83 eb 04                sub    $0x4,%ebx 804844a:       83 f8 ff                cmp    $0xffffffff,%eax 804844d:       75 f3                   jne    8048442 <__do_global_ctors_aux+0x16> 804844f:       83 c4 04                add    $0x4,%esp 8048452:       5b                      pop    %ebx 8048453:       5d                      pop    %ebp 8048454:       c3                      ret 8048455:       90                      nop 8048456:       90                      nop 8048457:       90                      nopDisassembly of section .fini:08048458 <_fini>: 8048458:       55                      push   %ebp 8048459:       89 e5                   mov    %esp,%ebp 804845b:       53                      push   %ebx 804845c:       e8 a7 fe ff ff          call   8048308 <__i686.get_pc_thunk.bx> 8048461:       81 c3 13 11 00 00       add    $0x1113,%ebx 8048467:       83 ec 04                sub    $0x4,%esp 804846a:       e8 9d fe ff ff          call   804830c <__do_global_dtors_aux> 804846f:       83 c4 04                add    $0x4,%esp 8048472:       5b                      pop    %ebx 8048473:       5d                      pop    %ebp 8048474:       c3                      ret      

對于那些着迷于底層程式設計細節的程式員來說,這是一個功能非常強大的工具,可用于研究編譯器和彙編器的輸出。細節資訊,比如這段代碼中所顯示的這些資訊,可以揭示有關本地處理器本身運作方式的很多内容。對該處理器制造商提供的技術文檔進行深入的研究,您可以收集關于一些有價值的資訊,通過這些資訊可以深入地了解内部的運作機制,因為功能程式提供了清晰的輸出。

類似地,readelf 程式也可以清楚地列出目标檔案中的内容。輸入下面的指令,您将可以看到這一點:

readelf -all a.out      

這個指令生成的輸出如清單 4 所示。ELF Header 為該檔案中所有段入口顯示了詳細的摘要。在列舉出這些 Header 中的内容之前,您可以看到 Header 的具體數目。在研究一個較大的目标檔案時,該資訊可能非常有用。

清單 4. readelf 指令的輸出

ELF Header:  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00  Class:                             ELF32  Data:                              2's complement, little endian  Version:                           1 (current)  OS/ABI:                            UNIX - System V  ABI Version:                       0  Type:                              EXEC (Executable file)  Machine:                           Intel 80386  Version:                           0x1  Entry point address:               0x80482c0  Start of program headers:          52 (bytes into file)  Start of section headers:          3504 (bytes into file)  Flags:                             0x0  Size of this header:               52 (bytes)  Size of program headers:           32 (bytes)  Number of program headers:         7  Size of section headers:           40 (bytes)  Number of section headers:         34  Section header string table index: 31Section Headers:  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al  [ 0]                   NULL            00000000 000000 000000 00      0   0  0  [ 1] .interp           PROGBITS        08048114 000114 000013 00   A  0   0  1  [ 2] .note.ABI-tag     NOTE            08048128 000128 000020 00   A  0   0  4  [ 3] .hash             HASH            08048148 000148 00002c 04   A  4   0  4  [ 4] .dynsym           DYNSYM          08048174 000174 000060 10   A  5   1  4  [ 5] .dynstr           STRTAB          080481d4 0001d4 00005e 00   A  0   0  1  [ 6] .gnu.version      VERSYM          08048232 000232 00000c 02   A  4   0  2  [ 7] .gnu.version_r    VERNEED         08048240 000240 000020 00   A  5   1  4  [ 8] .rel.dyn          REL             08048260 000260 000008 08   A  4   0  4  [ 9] .rel.plt          REL             08048268 000268 000010 08   A  4  11  4  [10] .init             PROGBITS        08048278 000278 000017 00  AX  0   0  1  [11] .plt              PROGBITS        08048290 000290 000030 04  AX  0   0  4  [12] .text             PROGBITS        080482c0 0002c0 000198 00  AX  0   0  4  [13] .fini             PROGBITS        08048458 000458 00001d 00  AX  0   0  1  [14] .rodata           PROGBITS        08048478 000478 000015 00   A  0   0  4  [15] .eh_frame         PROGBITS        08048490 000490 000004 00   A  0   0  4  [16] .ctors            PROGBITS        08049494 000494 000008 00  WA  0   0  4  [17] .dtors            PROGBITS        0804949c 00049c 000008 00  WA  0   0  4  [18] .jcr              PROGBITS        080494a4 0004a4 000004 00  WA  0   0  4  [19] .dynamic          DYNAMIC         080494a8 0004a8 0000c8 08  WA  5   0  4  [20] .got              PROGBITS        08049570 000570 000004 04  WA  0   0  4  [21] .got.plt          PROGBITS        08049574 000574 000014 04  WA  0   0  4  [22] .data             PROGBITS        08049588 000588 00000c 00  WA  0   0  4  [23] .bss              NOBITS          08049594 000594 000004 00  WA  0   0  4  [24] .comment          PROGBITS        00000000 000594 000126 00      0   0  1  [25] .debug_aranges    PROGBITS        00000000 0006c0 000088 00      0   0  8  [26] .debug_pubnames   PROGBITS        00000000 000748 000025 00      0   0  1  [27] .debug_info       PROGBITS        00000000 00076d 00022b 00      0   0  1  [28] .debug_abbrev     PROGBITS        00000000 000998 000076 00      0   0  1  [29] .debug_line       PROGBITS        00000000 000a0e 0001bb 00      0   0  1  [30] .debug_str        PROGBITS        00000000 000bc9 0000bf 01  MS  0   0  1  [31] .shstrtab         STRTAB          00000000 000c88 000127 00      0   0  1  [32] .symtab           SYMTAB          00000000 001300 000520 10     33  63  4  [33] .strtab           STRTAB          00000000 001820 0002d2 00      0   0  1Key to Flags:  W (write), A (alloc), X (execute), M (merge), S (strings)  I (info), L (link order), G (group), x (unknown)  O (extra OS processing required) o (OS specific), p (processor specific)There are no section groups in this file.Program Headers:  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align  PHDR           0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4  INTERP         0x000114 0x08048114 0x08048114 0x00013 0x00013 R   0x1      [Requesting program interpreter: /lib/ld-linux.so.2]  LOAD           0x000000 0x08048000 0x08048000 0x00494 0x00494 R E 0x1000  LOAD           0x000494 0x08049494 0x08049494 0x00100 0x00104 RW  0x1000  DYNAMIC        0x0004a8 0x080494a8 0x080494a8 0x000c8 0x000c8 RW  0x4  NOTE           0x000128 0x08048128 0x08048128 0x00020 0x00020 R   0x4  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4 Section to Segment mapping:  Segment Sections...   00   01     .interp   02     .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version           .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame   03     .ctors .dtors .jcr .dynamic .got .got.plt .data .bss   04     .dynamic   05     .note.ABI-tag   06Dynamic section at offset 0x4a8 contains 20 entries:  Tag        Type                         Name/Value 0x00000001 (NEEDED)                     Shared library: [libc.so.6] 0x0000000c (INIT)                       0x8048278 0x0000000d (FINI)                       0x8048458 0x00000004 (HASH)                       0x8048148 0x00000005 (STRTAB)                     0x80481d4 0x00000006 (SYMTAB)                     0x8048174 0x0000000a (STRSZ)                      94 (bytes) 0x0000000b (SYMENT)                     16 (bytes) 0x00000015 (DEBUG)                      0x0 0x00000003 (PLTGOT)                     0x8049574 0x00000002 (PLTRELSZ)                   16 (bytes) 0x00000014 (PLTREL)                     REL 0x00000017 (JMPREL)                     0x8048268 0x00000011 (REL)                        0x8048260 0x00000012 (RELSZ)                      8 (bytes) 0x00000013 (RELENT)                     8 (bytes) 0x6ffffffe (VERNEED)                    0x8048240 0x6fffffff (VERNEEDNUM)                 1 0x6ffffff0 (VERSYM)                     0x8048232 0x00000000 (NULL)                       0x0Relocation section '.rel.dyn' at offset 0x260 contains 1 entries: Offset     Info    Type            Sym.Value  Sym. Name08049570  00000506 R_386_GLOB_DAT    00000000   __gmon_start__Relocation section '.rel.plt' at offset 0x268 contains 2 entries: Offset     Info    Type            Sym.Value  Sym. Name08049580  00000107 R_386_JUMP_SLOT   00000000   puts08049584  00000207 R_386_JUMP_SLOT   00000000   __libc_start_mainThere are no unwind sections in this file.Symbol table '.dynsym' contains 6 entries:   Num:    Value  Size Type    Bind   Vis      Ndx Name     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND     1: 00000000   378 FUNC    GLOBAL DEFAULT  UND [email protected]_2.0 (2)     2: 00000000   230 FUNC    GLOBAL DEFAULT  UND [email protected]_2.0 (2)     3: 0804847c     4 OBJECT  GLOBAL DEFAULT   14 _IO_stdin_used     4: 00000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses     5: 00000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__Symbol table '.symtab' contains 82 entries:   Num:    Value  Size Type    Bind   Vis      Ndx Name     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND     1: 08048114     0 SECTION LOCAL  DEFAULT    1     2: 08048128     0 SECTION LOCAL  DEFAULT    2     3: 08048148     0 SECTION LOCAL  DEFAULT    3     4: 08048174     0 SECTION LOCAL  DEFAULT    4     5: 080481d4     0 SECTION LOCAL  DEFAULT    5     6: 08048232     0 SECTION LOCAL  DEFAULT    6     7: 08048240     0 SECTION LOCAL  DEFAULT    7     8: 08048260     0 SECTION LOCAL  DEFAULT    8     9: 08048268     0 SECTION LOCAL  DEFAULT    9    10: 08048278     0 SECTION LOCAL  DEFAULT   10    11: 08048290     0 SECTION LOCAL  DEFAULT   11    12: 080482c0     0 SECTION LOCAL  DEFAULT   12    13: 08048458     0 SECTION LOCAL  DEFAULT   13    14: 08048478     0 SECTION LOCAL  DEFAULT   14    15: 08048490     0 SECTION LOCAL  DEFAULT   15    16: 08049494     0 SECTION LOCAL  DEFAULT   16    17: 0804949c     0 SECTION LOCAL  DEFAULT   17    18: 080494a4     0 SECTION LOCAL  DEFAULT   18    19: 080494a8     0 SECTION LOCAL  DEFAULT   19    20: 08049570     0 SECTION LOCAL  DEFAULT   20    21: 08049574     0 SECTION LOCAL  DEFAULT   21    22: 08049588     0 SECTION LOCAL  DEFAULT   22    23: 08049594     0 SECTION LOCAL  DEFAULT   23    24: 00000000     0 SECTION LOCAL  DEFAULT   24    25: 00000000     0 SECTION LOCAL  DEFAULT   25    26: 00000000     0 SECTION LOCAL  DEFAULT   26    27: 00000000     0 SECTION LOCAL  DEFAULT   27    28: 00000000     0 SECTION LOCAL  DEFAULT   28    29: 00000000     0 SECTION LOCAL  DEFAULT   29    30: 00000000     0 SECTION LOCAL  DEFAULT   30    31: 00000000     0 SECTION LOCAL  DEFAULT   31    32: 00000000     0 SECTION LOCAL  DEFAULT   32    33: 00000000     0 SECTION LOCAL  DEFAULT   33    34: 00000000     0 FILE    LOCAL  DEFAULT  ABS abi-note.S    35: 00000000     0 FILE    LOCAL  DEFAULT  ABS ../sysdeps/i386/elf/start    36: 00000000     0 FILE    LOCAL  DEFAULT  ABS init.c    37: 00000000     0 FILE    LOCAL  DEFAULT  ABS initfini.c    38: 00000000     0 FILE    LOCAL  DEFAULT  ABS /build/buildd/glibc-2.3.6    39: 080482e4     0 FUNC    LOCAL  DEFAULT   12 call_gmon_start    40: 00000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c    41: 08049494     0 OBJECT  LOCAL  DEFAULT   16 __CTOR_LIST__    42: 0804949c     0 OBJECT  LOCAL  DEFAULT   17 __DTOR_LIST__    43: 080494a4     0 OBJECT  LOCAL  DEFAULT   18 __JCR_LIST__    44: 08049594     1 OBJECT  LOCAL  DEFAULT   23 completed.4463    45: 08049590     0 OBJECT  LOCAL  DEFAULT   22 p.4462    46: 0804830c     0 FUNC    LOCAL  DEFAULT   12 __do_global_dtors_aux    47: 0804833b     0 FUNC    LOCAL  DEFAULT   12 frame_dummy    48: 00000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c    49: 08049498     0 OBJECT  LOCAL  DEFAULT   16 __CTOR_END__    50: 080494a0     0 OBJECT  LOCAL  DEFAULT   17 __DTOR_END__    51: 08048490     0 OBJECT  LOCAL  DEFAULT   15 __FRAME_END__    52: 080494a4     0 OBJECT  LOCAL  DEFAULT   18 __JCR_END__    53: 0804842c     0 FUNC    LOCAL  DEFAULT   12 __do_global_ctors_aux    54: 00000000     0 FILE    LOCAL  DEFAULT  ABS initfini.c    55: 00000000     0 FILE    LOCAL  DEFAULT  ABS /build/buildd/glibc-2.3.6    56: 00000000     0 FILE    LOCAL  DEFAULT  ABS hw.c    57: 080494a8     0 OBJECT  LOCAL  HIDDEN   19 _DYNAMIC    58: 08049494     0 NOTYPE  LOCAL  HIDDEN  ABS __fini_array_end    59: 08049494     0 NOTYPE  LOCAL  HIDDEN  ABS __fini_array_start    60: 08049494     0 NOTYPE  LOCAL  HIDDEN  ABS __init_array_end    61: 08049574     0 OBJECT  LOCAL  HIDDEN   21 _GLOBAL_OFFSET_TABLE_    62: 08049494     0 NOTYPE  LOCAL  HIDDEN  ABS __init_array_start    63: 08048478     4 OBJECT  GLOBAL DEFAULT   14 _fp_hw    64: 0804958c     0 OBJECT  GLOBAL HIDDEN   22 __dso_handle    65: 080483e1    74 FUNC    GLOBAL DEFAULT   12 __libc_csu_fini    66: 00000000   378 FUNC    GLOBAL DEFAULT  UND [email protected]@GLIBC_2.0    67: 08048278     0 FUNC    GLOBAL DEFAULT   10 _init    68: 080482c0     0 FUNC    GLOBAL DEFAULT   12 _start    69: 08048390    81 FUNC    GLOBAL DEFAULT   12 __libc_csu_init    70: 08049594     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start    71: 08048360    47 FUNC    GLOBAL DEFAULT   12 main    72: 00000000   230 FUNC    GLOBAL DEFAULT  UND [email protected]@GLIBC_    73: 08049588     0 NOTYPE  WEAK   DEFAULT   22 data_start    74: 08048458     0 FUNC    GLOBAL DEFAULT   13 _fini    75: 08049594     0 NOTYPE  GLOBAL DEFAULT  ABS _edata    76: 08048308     0 FUNC    GLOBAL HIDDEN   12 __i686.get_pc_thunk.bx    77: 08049598     0 NOTYPE  GLOBAL DEFAULT  ABS _end    78: 0804847c     4 OBJECT  GLOBAL DEFAULT   14 _IO_stdin_used    79: 08049588     0 NOTYPE  GLOBAL DEFAULT   22 __data_start    80: 00000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses    81: 00000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__Histogram for bucket list length (total of 3 buckets): Length  Number     % of total  Coverage      0  0          (  0.0%)      1  1          ( 33.3%)     20.0%      2  2          ( 66.7%)    100.0%Version symbols section '.gnu.version' contains 6 entries: Addr: 0000000008048232  Offset: 0x000232  Link: 4 (.dynsym)  000:   0 (*local*)       2 (GLIBC_2.0)     2 (GLIBC_2.0)     1 (*global*)  004:   0 (*local*)       0 (*local*)Version needs section '.gnu.version_r' contains 1 entries: Addr: 0x0000000008048240  Offset: 0x000240  Link to section: 5 (.dynstr)  000000: Version: 1  File: libc.so.6  Cnt: 1  0x0010:   Name: GLIBC_2.0  Flags: none  Version: 2Notes at offset 0x00000128 with length 0x00000020:  Owner         Data size       Description  GNU           0x00000010      NT_VERSION (version)      

正如從該輸出中看到的,簡單的 a.out Hello World 檔案中包含了大量有價值的細節資訊,包括版本資訊、柱狀圖、各種符号類型的表格,等等。通過使用本文中介紹的這幾種工具分析目标檔案,您可以慢慢地對可執行程式進行研究。

除了所有這些段之外,編譯器可以将調試資訊放入到目标檔案中,并且還可以顯示這些資訊。輸入下面的指令,仔細分析編譯器的輸出(假設您扮演了調試程式的角色):

readelf --debug-dump a.out | less      

這個指令生成的輸出如清單 5 所示。調試工具,如 GDB,可以讀取這些調試資訊,并且當程式在調試器中運作的同時,您可以使用該工具顯示更具描述性的标記,而不是對代碼進行反彙編時的原始位址值。

清單 5. 該程式中的調試資訊

The section .debug_aranges contains:  Length:                   28  Version:                  2  Offset into .debug_info:  0  Pointer Size:             4  Segment Size:             0    Address  Length    080482c0 34  Length:                   52  Version:                  2  Offset into .debug_info:  10b  Pointer Size:             4  Segment Size:             0    Address  Length    08048308 4    08048458 18    08048278 11    080482e4 36  Length:                   44  Version:                  2  Offset into .debug_info:  19b  Pointer Size:             4  Segment Size:             0    Address  Length    08048308 4    0804846f 6    0804828d 2Contents of the .debug_pubnames section:  Length:                              33  Version:                             2  Offset into .debug_info section:     122  Size of area in .debug_info section: 145    Offset      Name    121                 _IO_stdin_usedThe section .debug_info contains:  Compilation Unit @ offset 0x0:   Length:        118   Version:       2   Abbrev Offset: 0   Pointer Size:  4 <0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)     DW_AT_stmt_list   : 0     DW_AT_low_pc      : 0x80482c0     DW_AT_high_pc     : 0x80482e2     DW_AT_name        : ../sysdeps/i386/elf/start.S     DW_AT_comp_dir    : /build/buildd/glibc-2.3.6/build-tree/glibc-2.3.6/csu     DW_AT_producer    : GNU AS 2.16.91     DW_AT_language    : 32769  (MIPS assembler)  Compilation Unit @ offset 0x7a:   Length:        141   Version:       2   Abbrev Offset: 20   Pointer Size:  4 <0><85>: Abbrev Number: 1 (DW_TAG_compile_unit)     DW_AT_stmt_list   : 0x5b     DW_AT_high_pc     : 0x80482e4     DW_AT_low_pc      : 0x80482e4     DW_AT_producer    : (indirect string, offset: 0x62): GNU C 3.4.6     DW_AT_language    : 1      (ANSI C)     DW_AT_name        : (indirect string, offset: 0x0): init.c     DW_AT_comp_dir    : (indirect string, offset: 0x11): /build/buildd/... <1><9f>: Abbrev Number: 2 (DW_TAG_base_type)     DW_AT_name        : (indirect string, offset: 0x90): unsigned int     DW_AT_byte_size   : 4     DW_AT_encoding    : 7      (unsigned) <1><a6>: Abbrev Number: 2 (DW_TAG_base_type)     DW_AT_name        : (indirect string, offset: 0x54): unsigned char     DW_AT_byte_size   : 1     DW_AT_encoding    : 8      (unsigned char) <1><ad>: Abbrev Number: 2 (DW_TAG_base_type)     DW_AT_name        : (indirect string, offset: 0x9d): short unsigned int     DW_AT_byte_size   : 2     DW_AT_encoding    : 7      (unsigned) <1><b4>: Abbrev Number: 2 (DW_TAG_base_type)     DW_AT_name        : (indirect string, offset: 0x8b): long unsigned int     DW_AT_byte_size   : 4     DW_AT_encoding    : 7      (unsigned) <1><bb>: Abbrev Number: 2 (DW_TAG_base_type)     DW_AT_name        : (indirect string, offset: 0x56): signed char     DW_AT_byte_size   : 1     DW_AT_encoding    : 6      (signed char) <1><c2>: Abbrev Number: 2 (DW_TAG_base_type)     DW_AT_name        : (indirect string, offset: 0x7): short int     DW_AT_byte_size   : 2     DW_AT_encoding    : 5      (signed) <1><c9>: Abbrev Number: 3 (DW_TAG_base_type)     DW_AT_name        : int     DW_AT_byte_size   : 4     DW_AT_encoding    : 5      (signed) <1><d0>: Abbrev Number: 2 (DW_TAG_base_type)     DW_AT_name        : (indirect string, offset: 0x46): long long int     DW_AT_byte_size   : 8     DW_AT_encoding    : 5      (signed) <1><d7>: Abbrev Number: 2 (DW_TAG_base_type)     DW_AT_name        : (indirect string, offset: 0x86): long long unsigned int     DW_AT_byte_size   : 8     DW_AT_encoding    : 7      (unsigned) <1><de>: Abbrev Number: 2 (DW_TAG_base_type)     DW_AT_name        : (indirect string, offset: 0x4b): long int     DW_AT_byte_size   : 4     DW_AT_encoding    : 5      (signed) <1><e5>: Abbrev Number: 2 (DW_TAG_base_type)     DW_AT_name        : (indirect string, offset: 0x90): unsigned int     DW_AT_byte_size   : 4     DW_AT_encoding    : 7      (unsigned) <1><ec>: Abbrev Number: 2 (DW_TAG_base_type)     DW_AT_name        : (indirect string, offset: 0x5d): char     DW_AT_byte_size   : 1     DW_AT_encoding    : 6      (signed char) <1><f3>: Abbrev Number: 4 (DW_TAG_variable)     DW_AT_name        : (indirect string, offset: 0xb0): _IO_stdin_used     DW_AT_decl_file   : 1     DW_AT_decl_line   : 25     DW_AT_type        : <105>     DW_AT_external    : 1     DW_AT_location    : 5 byte block: 3 7c 84 4 8      (DW_OP_addr: 804847c) <1><105>: Abbrev Number: 5 (DW_TAG_const_type)     DW_AT_type        : <c9>  Compilation Unit @ offset 0x10b:   Length:        140   Version:       2   Abbrev Offset: 86   Pointer Size:  4 <0><116>: Abbrev Number: 1 (DW_TAG_compile_unit)     DW_AT_stmt_list   : 0x82     DW_AT_name        : /build/buildd/glibc-2.3.6/build-tree/i386-libc/csu/crti.S     DW_AT_comp_dir    : /build/buildd/glibc-2.3.6/build-tree/glibc-2.3.6/csu     DW_AT_producer    : GNU AS 2.16.91     DW_AT_language    : 32769  (MIPS assembler)  Compilation Unit @ offset 0x19b:   Length:        140   Version:       2   Abbrev Offset: 102   Pointer Size:  4 <0><1a6>: Abbrev Number: 1 (DW_TAG_compile_unit)     DW_AT_stmt_list   : 0x12f     DW_AT_name        : /build/buildd/glibc-2.3.6/build-tree/i386-libc/csu/crtn.S     DW_AT_comp_dir    : /build/buildd/glibc-2.3.6/build-tree/glibc-2.3.6/csu     DW_AT_producer    : GNU AS 2.16.91     DW_AT_language    : 32769  (MIPS assembler)Contents of the .debug_abbrev section:  Number TAG   1      DW_TAG_compile_unit    [no children]    DW_AT_stmt_list    DW_FORM_data4    DW_AT_low_pc       DW_FORM_addr    DW_AT_high_pc      DW_FORM_addr    DW_AT_name         DW_FORM_string    DW_AT_comp_dir     DW_FORM_string    DW_AT_producer     DW_FORM_string    DW_AT_language     DW_FORM_data2  Number TAG   1      DW_TAG_compile_unit    [has children]    DW_AT_stmt_list    DW_FORM_data4    DW_AT_high_pc      DW_FORM_addr    DW_AT_low_pc       DW_FORM_addr    DW_AT_producer     DW_FORM_strp    DW_AT_language     DW_FORM_data1    DW_AT_name         DW_FORM_strp    DW_AT_comp_dir     DW_FORM_strp   2      DW_TAG_base_type    [no children]    DW_AT_name         DW_FORM_strp    DW_AT_byte_size    DW_FORM_data1    DW_AT_encoding     DW_FORM_data1   3      DW_TAG_base_type    [no children]    DW_AT_name         DW_FORM_string    DW_AT_byte_size    DW_FORM_data1    DW_AT_encoding     DW_FORM_data1   4      DW_TAG_variable    [no children]    DW_AT_name         DW_FORM_strp    DW_AT_decl_file    DW_FORM_data1    DW_AT_decl_line    DW_FORM_data1    DW_AT_type         DW_FORM_ref4    DW_AT_external     DW_FORM_flag    DW_AT_location     DW_FORM_block1   5      DW_TAG_const_type    [no children]    DW_AT_type         DW_FORM_ref4  Number TAG   1      DW_TAG_compile_unit    [no children]    DW_AT_stmt_list    DW_FORM_data4    DW_AT_name         DW_FORM_string    DW_AT_comp_dir     DW_FORM_string    DW_AT_producer     DW_FORM_string    DW_AT_language     DW_FORM_data2  Number TAG   1      DW_TAG_compile_unit    [no children]    DW_AT_stmt_list    DW_FORM_data4    DW_AT_name         DW_FORM_string    DW_AT_comp_dir     DW_FORM_string    DW_AT_producer     DW_FORM_string    DW_AT_language     DW_FORM_data2Dump of debug contents of section .debug_line:  Length:                      87  DWARF Version:               2  Prologue Length:             50  Minimum Instruction Length:  1  Initial value of 'is_stmt':  1  Line Base:                   -5  Line Range:                  14  Opcode Base:                 13  (Pointer size:               4) Opcodes:  Opcode 1 has 0 args  Opcode 2 has 1 args  Opcode 3 has 1 args  Opcode 4 has 1 args  Opcode 5 has 1 args  Opcode 6 has 0 args  Opcode 7 has 0 args  Opcode 8 has 0 args  Opcode 9 has 1 args  Opcode 10 has 0 args  Opcode 11 has 0 args  Opcode 12 has 1 args The Directory Table:  ../sysdeps/i386/elf The File Name Table:  Entry Dir     Time    Size    Name  1     1       0       0       start.S Line Number Statements:  Extended opcode 2: set Address to 0x80482c0  Advance Line by 64 to 65  Copy  Special opcode 38: advance Address by 2 to 0x80482c2 and Line by 5 to 70  Special opcode 20: advance Address by 1 to 0x80482c3 and Line by 1 to 71  Special opcode 39: advance Address by 2 to 0x80482c5 and Line by 6 to 77  Special opcode 48: advance Address by 3 to 0x80482c8 and Line by 1 to 78  Special opcode 24: advance Address by 1 to 0x80482c9 and Line by 5 to 83  Special opcode 21: advance Address by 1 to 0x80482ca and Line by 2 to 85  Advance Line by 24 to 109  Special opcode 19: advance Address by 1 to 0x80482cb and Line by 0 to 109  Special opcode 76: advance Address by 5 to 0x80482d0 and Line by 1 to 110  Special opcode 77: advance Address by 5 to 0x80482d5 and Line by 2 to 112  Special opcode 20: advance Address by 1 to 0x80482d6 and Line by 1 to 113  Special opcode 21: advance Address by 1 to 0x80482d7 and Line by 2 to 115  Special opcode 79: advance Address by 5 to 0x80482dc and Line by 4 to 119  Special opcode 78: advance Address by 5 to 0x80482e1 and Line by 3 to 122  Advance PC by 1 to 0x80482e2  Extended opcode 1: End of Sequence  Length:                      35  DWARF Version:               2  Prologue Length:             29  Minimum Instruction Length:  1  Initial value of 'is_stmt':  1  Line Base:                   -5  Line Range:                  14  Opcode Base:                 13  (Pointer size:               4) Opcodes:  Opcode 1 has 0 args  Opcode 2 has 1 args  Opcode 3 has 1 args  Opcode 4 has 1 args  Opcode 5 has 1 args  Opcode 6 has 0 args  Opcode 7 has 0 args  Opcode 8 has 0 args  Opcode 9 has 1 args  Opcode 10 has 0 args  Opcode 11 has 0 args  Opcode 12 has 1 args The Directory Table is empty. The File Name Table:  Entry Dir     Time    Size    Name  1     0       0       0       init.c Line Number Statements:  Length:                      169  DWARF Version:               2  Prologue Length:             80  Minimum Instruction Length:  1  Initial value of 'is_stmt':  1  Line Base:                   -5  Line Range:                  14  Opcode Base:                 13  (Pointer size:               4) Opcodes:  Opcode 1 has 0 args  Opcode 2 has 1 args  Opcode 3 has 1 args  Opcode 4 has 1 args  Opcode 5 has 1 args  Opcode 6 has 0 args  Opcode 7 has 0 args  Opcode 8 has 0 args  Opcode 9 has 1 args  Opcode 10 has 0 args  Opcode 11 has 0 args  Opcode 12 has 1 args The Directory Table:  /build/buildd/glibc-2.3.6/build-tree/i386-libc/csu The File Name Table:  Entry Dir     Time    Size    Name  1     1       0       0       crti.S Line Number Statements:  Extended opcode 2: set Address to 0x8048308  Advance Line by 64 to 65  Copy  Special opcode 48: advance Address by 3 to 0x804830b and Line by 1 to 66  Advance PC by 1 to 0x804830c  Extended opcode 1: End of Sequence  Extended opcode 2: set Address to 0x8048458  Advance Line by 46 to 47  Copy  Special opcode 20: advance Address by 1 to 0x8048459 and Line by 1 to 48  Special opcode 34: advance Address by 2 to 0x804845b and Line by 1 to 49  Special opcode 20: advance Address by 1 to 0x804845c and Line by 1 to 50  Special opcode 76: advance Address by 5 to 0x8048461 and Line by 1 to 51  Special opcode 90: advance Address by 6 to 0x8048467 and Line by 1 to 52  Advance PC by 3 to 0x804846a  Extended opcode 1: End of Sequence  Extended opcode 2: set Address to 0x8048278  Advance Line by 31 to 32  Copy  Special opcode 20: advance Address by 1 to 0x8048279 and Line by 1 to 33  Special opcode 34: advance Address by 2 to 0x804827b and Line by 1 to 34  Special opcode 48: advance Address by 3 to 0x804827e and Line by 1 to 35  Advance PC by 5 to 0x8048283  Extended opcode 1: End of Sequence  Extended opcode 2: set Address to 0x80482e4  Advance Line by 10 to 11  Copy  Special opcode 20: advance Address by 1 to 0x80482e5 and Line by 1 to 12  Special opcode 34: advance Address by 2 to 0x80482e7 and Line by 1 to 13  Special opcode 20: advance Address by 1 to 0x80482e8 and Line by 1 to 14  Special opcode 76: advance Address by 5 to 0x80482ed and Line by 1 to 15  Special opcode 90: advance Address by 6 to 0x80482f3 and Line by 1 to 16  Special opcode 48: advance Address by 3 to 0x80482f6 and Line by 1 to 17  Special opcode 90: advance Address by 6 to 0x80482fc and Line by 1 to 18  Special opcode 34: advance Address by 2 to 0x80482fe and Line by 1 to 19  Special opcode 34: advance Address by 2 to 0x8048300 and Line by 1 to 20  Special opcode 35: advance Address by 2 to 0x8048302 and Line by 2 to 22  Special opcode 48: advance Address by 3 to 0x8048305 and Line by 1 to 23  Special opcode 20: advance Address by 1 to 0x8048306 and Line by 1 to 24  Special opcode 20: advance Address by 1 to 0x8048307 and Line by 1 to 25  Advance PC by 1 to 0x8048308  Extended opcode 1: End of Sequence  Length:                      136  DWARF Version:               2  Prologue Length:             80  Minimum Instruction Length:  1  Initial value of 'is_stmt':  1  Line Base:                   -5  Line Range:                  14  Opcode Base:                 13  (Pointer size:               4) Opcodes:  Opcode 1 has 0 args  Opcode 2 has 1 args  Opcode 3 has 1 args  Opcode 4 has 1 args  Opcode 5 has 1 args  Opcode 6 has 0 args  Opcode 7 has 0 args  Opcode 8 has 0 args  Opcode 9 has 1 args  Opcode 10 has 0 args  Opcode 11 has 0 args  Opcode 12 has 1 args The Directory Table:  /build/buildd/glibc-2.3.6/build-tree/i386-libc/csu The File Name Table:  Entry Dir     Time    Size    Name  1     1       0       0       crtn.S Line Number Statements:  Extended opcode 2: set Address to 0x8048308  Advance Line by 33 to 34  Copy  Special opcode 48: advance Address by 3 to 0x804830b and Line by 1 to 35  Advance PC by 1 to 0x804830c  Extended opcode 1: End of Sequence  Extended opcode 2: set Address to 0x804846f  Advance Line by 18 to 19  Copy  Special opcode 48: advance Address by 3 to 0x8048472 and Line by 1 to 20  Special opcode 20: advance Address by 1 to 0x8048473 and Line by 1 to 21  Special opcode 20: advance Address by 1 to 0x8048474 and Line by 1 to 22  Advance PC by 1 to 0x8048475  Extended opcode 1: End of Sequence  Extended opcode 2: set Address to 0x804828d  Advance Line by 9 to 10  Copy  Special opcode 20: advance Address by 1 to 0x804828e and Line by 1 to 11  Advance PC by 1 to 0x804828f  Extended opcode 1: End of SequenceContents of the .debug_str section:  0x00000000 696e6974 2e630073 686f7274 20696e74 init.c.short int  0x00000010 002f6275 696c642f 6275696c 64642f67 ./build/buildd/g  0x00000020 6c696263 2d322e33 2e362f62 75696c64 libc-2.3.6/build  0x00000030 2d747265 652f676c 6962632d 322e332e -tree/glibc-2.3.  0x00000040 362f6373 75006c6f 6e67206c 6f6e6720 6/csu.long long  0x00000050 696e7400 756e7369 676e6564 20636861 int.unsigned cha  0x00000060 7200474e 55204320 332e342e 36202855 r.GNU C 3.4.6 (U  0x00000070 62756e74 7520332e 342e362d 31756275 buntu 3.4.6-1ubu  0x00000080 6e747532 29006c6f 6e67206c 6f6e6720 ntu2).long long  0x00000090 756e7369 676e6564 20696e74 0073686f unsigned int.sho  0x000000a0 72742075 6e736967 6e656420 696e7400 rt unsigned int.  0x000000b0 5f494f5f 73746469 6e5f7573 656400   _IO_stdin_used.      

可執行檔案是目标檔案

在 UNIX 中,可執行檔案是 目标檔案,并且您可以像對 a.out 檔案那樣對它們進行分析。可以進行一次有益的練習,更改到 /bin 或 /local/bin 目錄,然後針對一些您最常用的指令,如

pwd

ps

cat

rm

,運作

nm

objdump

readelf

。通常,在您編寫需要某種功能的程式時,如果标準的工具已經提供了這個功能,那麼通過運作

objdump -d <command>

,可以檢視這些工具究竟如何完成這項任務。

如果您傾向于使用編譯器和其他的語言工具,那麼您可以對組成計算機系統的各種目标檔案進行仔細研究,并且您将會發現這項工作是非常值得的。UNIX 作業系統具有許多層次,那些通過工具檢視目标檔案所公開的層次,非常接近底層硬體。通過這種方式,您可以真實地接觸到系統。

結束語

研究目标檔案可以極大地加深您對 UNIX 作業系統的認識,并且可以更深入地了解如何對軟體的源代碼進行彙編。我鼓勵您使用本文中介紹的目标檔案工具對系統中 /bin 或 /local/bin 目錄中的程式進行分析,仔細研究其輸出結果,并找出您的硬體制造商所提供的系統文檔。

當我們的程式中有經常使用的子產品,而且這種子產品在其他程式中也會用到,這時按照軟體重用的思想,我們應該将它們生成庫,使得以後程式設計可以減少開發代碼量。這裡介紹兩個指令ar和nm,用來對庫操作。

1.ar基本用法

2.nm基本用法指令

 當我們的程式中有經常使用的子產品,而且這種子產品在其他程式中也會用到,這時按照軟體重用的思想,我們應該将它們生成庫,使得以後程式設計可以減少開發代碼量。這裡介紹兩個指令ar和nm,用來對庫操作。

1.ar基本用法

  ar指令可以用來建立、修改庫,也可以從庫中提出單個子產品。庫是一單獨的檔案,裡面包含了按照特定的結構組織起來的其它的一些檔案(稱做此庫檔案的member)。原始檔案的内容、模式、時間戳、屬主、組等屬性都保留在庫檔案中。

  下面是ar指令的格式:

ar [-]{dmpqrtx}[abcfilNoPsSuvV] [membername] [count] archive files...

  例如我們可以用ar rv libtest.a hello.o hello1.o來生成一個庫,庫名字是test,連結時可以用-ltest連結。該庫中存放了兩個子產品hello.o和hello1.o。選項前可以有‘-'字元,也可以沒有。下面我們來看看指令的操作選項和任選項。現在我們把{dmpqrtx}部分稱為操作選項,而[abcfilNoPsSuvV]部分稱為任選項。

  {dmpqrtx}中的操作選項在指令中隻能并且必須使用其中一個,它們的含義如下:

d:從庫中删除子產品。按子產品原來的檔案名指定要删除的子產品。如果使用了任選項v則列出被删除的每個子產品。

m:該操作是在一個庫中移動成員。當庫中如果有若幹子產品有相同的符号定義(如函數定義),則成員的位置順序很重要。如果沒有指定任選項,任何指定的成員将移到庫的最後。也可以使用'a','b',或'I'任選項移動到指定的位置。

p:顯示庫中指定的成員到标準輸出。如果指定任選項v,則在輸出成員的内容前,将顯示成員的名字。如果沒有指定成員的名字,所有庫中的檔案将顯示出來。

q:快速追加。增加新子產品到庫的結尾處。并不檢查是否需要替換。'a','b',或'I'任選項對此操作沒有影響,子產品總是追加的庫的結尾處。如果使用了任選項v則列出每個子產品。 這時,庫的符号表沒有更新,可以用'ar s'或ranlib來更新庫的符号表索引。

r:在庫中插入子產品(替換)。當插入的子產品名已經在庫中存在,則替換同名的子產品。如果若幹子產品中有一個子產品在庫中不存在,ar顯示一個錯誤消息,并不替換其他同名子產品。預設的情況下,新的成員增加在庫的結尾處,可以使用其他任選項來改變增加的位置。

t:顯示庫的子產品表清單。一般隻顯示子產品名。

x:從庫中提取一個成員。如果不指定要提取的子產品,則提取庫中所有的子產品。

  下面在看看可與操作選項結合使用的任選項:

a:在庫的一個已經存在的成員後面增加一個新的檔案。如果使用任選項a,則應該為指令行中membername參數指定一個已經存在的成員名。

b:在庫的一個已經存在的成員前面增加一個新的檔案。如果使用任選項b,則應該為指令行中membername參數指定一個已經存在的成員名。

c:建立一個庫。不管庫是否存在,都将建立。

f:在庫中截短指定的名字。預設情況下,檔案名的長度是不受限制的,可以使用此參數将檔案名截短,以保證與其它系統的相容。

i:在庫的一個已經存在的成員前面增加一個新的檔案。如果使用任選項i,則應該為指令行中membername參數指定一個已經存在的成員名(類似任選項b)。

l:暫未使用

N:與count參數一起使用,在庫中有多個相同的檔案名時指定提取或輸出的個數。

o:當提取成員時,保留成員的原始資料。如果不指定該任選項,則提取出的子產品的時間将标為提取出的時間。

P:進行檔案名比對時使用全路徑名。ar在建立庫時不能使用全路徑名(這樣的庫檔案不符合POSIX标準),但是有些工具可以。

s:寫入一個目标檔案索引到庫中,或者更新一個存在的目标檔案索引。甚至對于沒有任何變化的庫也作該動作。對一個庫做ar s等同于對該庫做ranlib。

S:不建立目标檔案索引,這在建立較大的庫時能加快時間。

u:一般說來,指令ar r...插入所有列出的檔案到庫中,如果你隻想插入列出檔案中那些比庫中同名檔案新的檔案,就可以使用該任選項。該任選項隻用于r操作選項。

v:該選項用來顯示執行操作選項的附加資訊。

V:顯示ar的版本。

2.nm基本用法指令

  nm用來列出目标檔案的符号清單。下面是nm指令的格式:

nm [-a|--debug-syms] [-g|--extern-only] [-B][-C|--demangle] [-D|--dynamic] [-s|--print-armap][-o|--print-file-name] [-n|--numeric-sort][-p|--no-sort] [-r|--reverse-sort] [--size-sort][-u|--undefined-only] [-l|--line-numbers] [--help][--version] [-t radix|--radix=radix][-P|--portability] [-f format|--format=format][--target=bfdname] [objfile...]

  如果沒有為nm指令指出目标檔案,則nm假定目标檔案是a.out。下面列出該指令的任選項,大部分支援"-"開頭的短格式和"—"開頭的長格式。

-A、-o或--print-file-name:在找到的各個符号的名字前加上檔案名,而不是在此檔案的所有符号前隻出現檔案名一次。

例如nm libtest.a的輸出如下:

CPThread.o:

00000068 T Main__8CPThreadPv

00000038 T Start__8CPThread

00000014 T _._8CPThread

00000000 T __8CPThread

00000000 ? __FRAME_BEGIN__

.......................................

則nm -A 的輸出如下:

libtest.a:CPThread.o:00000068 T Main__8CPThreadPv

libtest.a:CPThread.o:00000038 T Start__8CPThread

libtest.a:CPThread.o:00000014 T _._8CPThread

libtest.a:CPThread.o:00000000 T __8CPThread

libtest.a:CPThread.o:00000000 ? __FRAME_BEGIN__

..................................................................

-a或--debug-syms:顯示調試符号。

-B:等同于--format=bsd,用來相容MIPS的nm。

-C或--demangle:将低級符号名解碼(demangle)成使用者級名字。這樣可以使得C++函數名具有可讀性。

-D或--dynamic:顯示動态符号。該任選項僅對于動态目标(例如特定類型的共享庫)有意義。

-f format:使用format格式輸出。format可以選取bsd、sysv或posix,該選項在GNU的nm中有用。預設為bsd。

-g或--extern-only:僅顯示外部符号。

-n、-v或--numeric-sort:按符号對應位址的順序排序,而非按符号名的字元順序。

-p或--no-sort:按目标檔案中遇到的符号順序顯示,不排序。

-P或--portability:使用POSIX.2标準輸出格式代替預設的輸出格式。等同于使用任選項-f posix。

-s或--print-armap:當列出庫中成員的符号時,包含索引。索引的内容包含:哪些子產品包含哪些名字的映射。

-r或--reverse-sort:反轉排序的順序(例如,升序變為降序)。

--size-sort:按大小排列符号順序。該大小是按照一個符号的值與它下一個符号的值進行計算的。

-t radix或--radix=radix:使用radix進制顯示符号值。radix隻能為"d"表示十進制、"o"表示八進制或"x"表示十六進制。

--target=bfdname:指定一個目标代碼的格式,而非使用系統的預設格式。

-u或--undefined-only:僅顯示沒有定義的符号(那些外部符号)。

-l或--line-numbers:對每個符号,使用調試資訊來試圖找到檔案名和行号。對于已定義的符号,查找符号位址的行号。對于未定義符号,查找指向符号重定位入口的行号。如果可以找到行号資訊,顯示在符号資訊之後。

-V或--version:顯示nm的版本号。

--help:顯示nm的任選項。 

1、ldd不是一個可執行程式,而隻是一個shell腳本。

2、ldd能夠顯示可執行子產品的dependency。

原理:通過設定一系列的環境變量,如:LD_TRACE_LOADED_OBJECTS、LD_WARN、LD_BIND_NOW、LD_LIBRARY_VERSION、 LD_VERBOSE等。當LD_TRACE_LOADED_OBJECTS環境變量不為空,任何可執行程式在運作時,都會隻顯示子產品的 dependency,而程式并不真正執行。我們可以在shell終端測試一下,具體測試如下:

(1) export LD_TRACE_LOADED_OBJECTS=1

(2) 再執行任何的程式,如ls等,看看程式的運作結果

3、ldd顯示可執行子產品dependency的工作原理,實質是通過ld-linux.so(elf動态庫的裝載器)來實作的。

衆所周知,ld-linux.so子產品會先于executable子產品程式工作,并獲得控制權,是以當上述的那些環境變量被設定時,ld-linux.so選擇了顯示可執行子產品的dependency。

4、實際上我們可以直接執行ld-linux.so子產品。如:/lib/ld-linux.so.2 --list program(這相當于ldd program)

ldd指令使用方法(摘自ldd --help)

名稱 ldd - 列印共享庫的依賴關系

大綱 ldd [選項]... 檔案...

描述 ldd 輸出在指令行上指定的每個程式或共享庫需要的共享庫。

選項

--version

列印ldd的版本号

-v --verbose

列印所有資訊,例如包括符号的版本資訊

-d --data-relocs

執行符号重部署,并報告缺少的目标對象(隻對ELF格式适用)

-r --function-relocs

對目标對象和函數執行重新部署,并報告缺少的目标對象和函數(隻對ELF格式适用)

--help 用法資訊

注意事項:

ldd的标準版本與glibc2一起提供。Libc5與老版本以前提供,在一些系統中還存在。在libc5版本中長選項不支援。另一方面,glibc2版本不支援-V選項,隻提供等價的--version選項。

如果指令行中給定的庫名字包含'/',這個程式的libc5版本将使用它作為庫名字;否則它将在标準位置搜尋庫。運作一個目前目錄下的共享庫,加字首"./"。

5、相關說明:

ldd不能工作在a.out格式的共享庫上。

ldd不能工作在一些非常老的a.out程式上,這些程式在支援ldd的編譯器發行前已經建立。如果你在這種類型的程式上使用ldd,程式将嘗試argc = 0的運作方式,其結果不可預知。

繼續閱讀