欧美vvv,亚洲第一成人在线,亚洲成人欧美日韩在线观看,日本猛少妇猛色XXXXX猛叫

新聞資訊

    一:背景

    1. 講故事

    前幾天公眾號(hào)里有位兄弟看了幾篇文章之后,也準(zhǔn)備用windbg試試看,結(jié)果這一配就花了好幾天,(づ╥﹏╥)づ,我想也有很多躍躍欲試的朋友在配置的時(shí)候肯定會(huì)遇到這樣和那樣的問題,所以我覺得有必要整理一下,讓大家少走彎路。

    二:一些基礎(chǔ)概念

    1. 在哪下載

    現(xiàn)在安裝windbg越來(lái)越麻煩,還要安裝Windows 10 SDK,很多人就栽在這里,其實(shí)大家可以直接在網(wǎng)上找一鍵打包的windbg 6.0版本即可,才30多M,調(diào)生產(chǎn)調(diào)本地都很方便,順帶還可以練練SOS命令。

    云盤:https://pan.baidu.com/s/1VqXVIGVHxAZVPNds1525Jg 提取碼:mahg

    外網(wǎng):http://www.33lc.com/soft/96743.html

    2. 版本問題

    解壓打開會(huì)有一個(gè)x64和x86文件夾,很顯然,32位的程序用x86下的windbg調(diào)試,64位的程序用x64的windbg調(diào)試,如下圖:

    3. 其他的問題

    我比較喜歡用64bit程序,所以這里使用64位的windbg。

    <1> 配置微軟公有符號(hào)

    符號(hào)其實(shí)就是pdb文件,我們?cè)赿ebug模式下編譯項(xiàng)目都會(huì)看到這個(gè),它的作用會(huì)對(duì)dll進(jìn)行打標(biāo),這樣在調(diào)試時(shí)通過(guò)pdb就能看到局部變量,全局變量,行號(hào)等等其他信息,在FCL類庫(kù)中的pdb文件就放在微軟的公有服務(wù)器上,SRV*C:\mysymbols*http://msdl.microsoft.com/download/symbols。

    <2> 理解sos.dll和clr.dll

    很多時(shí)候大家都是事后調(diào)試,所以需要在生產(chǎn)上抓一個(gè)dump文件,為了將dump文件逆向到clr上的運(yùn)行時(shí)狀態(tài),你必須要尋找到當(dāng)時(shí)運(yùn)行程序clr版本,同時(shí)也要找到對(duì)應(yīng)clr版本的sos.dll,他們通常是在一起的,sos 就是 你 和 clr交互的渠道,很多人都卡在尋找正確版本的sos和clr版本上。。。如果不清楚,我可以畫張圖。

    有了這個(gè)前置基礎(chǔ),接下來(lái)就可以在windows和centos上進(jìn)行配置實(shí)踐了。。。

    三. windows上的 netcore 3.1 配置

    為了演示,我先上一段簡(jiǎn)單的代碼:

    
            static void Main(string[] args)
            {
                var info = "hello world!";
                Console.WriteLine(info);
                Console.ReadLine();
            }
    

    1. 尋找clr.dll

    在netcore中,clr的名字變成了 coreclr.dll,路徑: C:\Program Files\dotnet\shared\Microsoft.NETCore.App.1.3

    2. 尋找sos.dll

    netcore3.0開始,sos就沒有放在版本號(hào)文件下了,詳見 SOS_README.md 內(nèi)容。

    
    SOS and other diagnostic tools now ship of band and work with any version of the .NET Core runtime.
    SOS has moved to the diagnostics repo here: https://github.com/dotnet/diagnostics.git.
    Instructions to install SOS: https://github.com/dotnet/diagnostics#installing-sos.
    

    看了上面文檔,大概意思就是說(shuō)老版本的windbg,需要通過(guò)小工具dotnet-sos 自己生成一個(gè)sos.dll,那就按照文檔來(lái)吧

    
    PS C:\WINDOWS\system32> dotnet tool install -g dotnet-sos
    You can invoke the tool using the following command: dotnet-sos
    Tool 'dotnet-sos' (version '3.1.122203') was successfully installed.
    PS C:\WINDOWS\system32> dotnet-sos install
    Installing SOS to C:\Users\hxc\.dotnet\sos from C:\Users\hxc\.dotnet\tools\.store\dotnet-sos\3.1.122203\dotnet-sos\3.1.122203\tools\netcoreapp2.1\any\win-x64
    Installing over existing installation...
    Creating installation directory...
    Copying files...
    Execute '.load C:\Users\hxc\.dotnet\sos\sos.dll' to load SOS in your Windows debugger.
    Cleaning up...
    SOS install succeeded
    PS C:\WINDOWS\system32>
    

    仔細(xì)看輸出,sos.dll 已經(jīng)生成好了,接下來(lái)在任務(wù)管理器中生成一個(gè)dump文件,然后使用 .load 命令把 coreclr 和 sos 加載進(jìn)去即可。

    
    .load C:\Users\hxc\.dotnet\sos\sos.dll
    .load C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.1.3\coreclr.dll
    

    最后我們抓一下 info 變量在堆上的分布。

    0:000> ~0s
    ntdll!ZwReadFile+0x14:
    00007ff8`3228aa64 c3              ret
    
    0:000> !clrstack -l
    OS Thread Id: 0x41d4 (0)
    
    000000246097EA40 00007FFF89C50F97 Error: Fail to initialize CoreCLR 80131022
    ConsoleApp5.Program.Main(System.String[])
        LOCALS:
            0x000000246097EA68 = 0x0000021d8141aba8
    
    0:000> !do 0x0000021d8141aba8
    Name:        System.String
    MethodTable: 00007fff89cd1e18
    EEClass:     00007fff89cc2128
    Size:        46(0x2e) bytes
    File:        C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.1.3\System.Private.CoreLib.dll
    String:      hello world!
    Fields:
                  MT    Field   Offset                 Type VT     Attr            Value Name
    00007fff89c1b1e8  4000242        8         System.Int32  1 instance               12 _stringLength
    00007fff89c18000  4000243        c          System.Char  1 instance               68 _firstChar
    00007fff89cd1e18  4000244      110        System.String  0   static 0000021d81411360 Empty
    

    好了,windows上的netcore調(diào)試就這么簡(jiǎn)單,希望這些配置能節(jié)省您的時(shí)間。

    四. windows 上的 netframework 配置

    framework程序比netcore配置要方便的多,不需要自己去生成sos了,如下代碼所示:

    
    64位程序加載路徑
    
     .load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\sos.dll
     .load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
    
    32位程序加載路徑
    
     .load C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll
     .load C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
    

    五. centos 上的 netcore 3.1 配置

    首先要明白,對(duì)于linux內(nèi)核windbg就失效了,那怎么調(diào)試呢? 有兩種方式。

    1. 使用netcore內(nèi)置的dotnet-dump 小工具

    這個(gè)工具的地方在于,sos和clr都不需要你配置,直接使用它生成dump,然后直接調(diào)試,方便至極,下面看看怎么安裝,開兩個(gè)terminal,如下代碼:

    
    terminal 1:
    
    [root@10-25-198-96 data]# dotnet build
    [root@10-25-198-96 netcoreapp3.1]# dotnet data.dll
    hello world
    
    
    terminal 2:
    
    [root@10-25-198-96 cs2]# ps -ef | grep dotnet
    root     31555 31247  0 22:28 pts/0    00:00:00 dotnet cs2.dll
    root     32112 31995  0 22:29 pts/2    00:00:00 grep --color=auto dotnet
    
    [root@10-25-198-96 cs2]# dotnet tool install -g dotnet-dump
    You can invoke the tool using the following command: dotnet-dump
    Tool 'dotnet-dump' (version '3.1.122203') was successfully installed.
    [root@10-25-198-96 cs2]# export PATH=$PATH:$HOME/.dotnet/tools
    [root@10-25-198-96 cs2]# dotnet-dump collect --process-id 31555
    Writing full to /cs2/core_20200508_223204
    Complete
    

    可以看到dump文件已經(jīng)好了 /cs2/core_20200508_223204 ,接下來(lái)用 dotnet-dump 對(duì)dump文件調(diào)試。

    
    [root@10-25-198-96 cs2]# dotnet-dump analyze /cs2/core_20200508_223204
    Loading core dump: /cs2/core_20200508_223204 ...
    Ready to process analysis commands. Type 'help' to list available commands or 'help [command]' to get detailed help on a command.
    Type 'quit' or 'exit' to exit the session.
    > clrstack -l                                                                                              
    OS Thread Id: 0x7b43 (0)
            Child SP               IP Call Site
    00007FFDFCABF2D0 00007fb0397af7fd [InlinedCallFrame: 00007ffdfcabf2d0] Interop+Sys.ReadStdin(Byte*, Int32)
    00007FFDFCABF2D0 00007fafbebbb4db [InlinedCallFrame: 00007ffdfcabf2d0] Interop+Sys.ReadStdin(Byte*, Int32)
    00007FFDFCABF2C0 00007FAFBEBBB4DB ILStubClass.IL_STUB_PInvoke(Byte*, Int32)
    
    00007FFDFCABF9D0 00007FAFBECF844D System.Console.ReadLine()
    
    00007FFDFCABF9E0 00007FAFBEBB037D cs2.Program.Main(System.String[]) [/cs2/Program.cs @ 13]
        LOCALS:
            0x00007FFDFCABF9F0 = 0x00007faf980081d8
    
    00007FFDFCABFD08 00007fb037fc0f7f [GCFrame: 00007ffdfcabfd08] 
    00007FFDFCAC01F0 00007fb037fc0f7f [GCFrame: 00007ffdfcac01f0] 
    > dumpobj 0x00007faf980081d8                                                                               
    Name:        System.String
    MethodTable: 00007fafbec30f90
    EEClass:     00007fafbeb9e1b0
    Size:        44(0x2c) bytes
    File:        /usr/share/dotnet/shared/Microsoft.NETCore.App/3.1.3/System.Private.CoreLib.dll
    String:      hello world
    Fields:
                  MT    Field   Offset                 Type VT     Attr            Value Name
    00007fafbec2a0e8  400022a        8         System.Int32  1 instance               11 _stringLength
    00007fafbec26f00  400022b        c          System.Char  1 instance               68 _firstChar
    00007fafbec30f90  400022c      108        System.String  0   static 00007faf97fff360 Empty
    >    
    

    就這么簡(jiǎn)單,不過(guò)這個(gè)工具雖好,但是不能調(diào)試非托管堆,而且命令也不是太多,當(dāng)然夠我們平時(shí)用了。

    2. 使用linux專屬的lldb調(diào)試器

    要想實(shí)現(xiàn)windbg級(jí)別的調(diào)試,可以使用lldb調(diào)試器,這個(gè)非常強(qiáng)大,這里我也來(lái)介紹一下吧。

    <1> 安裝lldb

    lldb是使用C++寫的,也可以在 https://github.com/dotnet/diagnostics/blob/master/documentation/building/linux-instructions.md 尋找安裝辦法。

    
    sudo yum install centos-release-SCL epel-release
    sudo yum install cmake cmake3 gcc gcc-c++ gdb git libicu libunwind make python27 tar wget which zip
    cd $HOME
    git clone https://github.com/dotnet/diagnostics.git
    $HOME/diagnostics/documentation/lldb/centos7/build-install-lldb.sh
    

    一陣抽搐后就安裝好了,從下面可以看到目前版本是3.9.1。

    
    [root@10-25-198-96 cs2]# lldb -v
    lldb version 3.9.1 ( revision )
    

    <2> 尋找sos.dll

    跟windbg一樣,你需要生成一個(gè)sos.dll 。。。 同樣也是使用 dotnet-sos 生成。

    
    [root@10-25-198-96 cs2]# dotnet tool install -g dotnet-sos
    You can invoke the tool using the following command: dotnet-sos
    Tool 'dotnet-sos' (version '3.1.122203') was successfully installed.
    [root@10-25-198-96 cs2]# dotnet-sos install
    Installing SOS to /root/.dotnet/sos from /root/.dotnet/tools/.store/dotnet-sos/3.1.122203/dotnet-sos/3.1.122203/tools/netcoreapp2.1/any/linux-x64
    Installing over existing installation...
    Creating installation directory...
    Copying files...
    Updating existing /root/.lldbinit file - LLDB will load SOS automatically at startup
    Cleaning up...
    SOS install succeeded
    

    從上面信息看,sos 是安裝在 /root/.dotnet/sos 目錄下,同時(shí)也看到在lldb啟動(dòng)的時(shí)候會(huì)自動(dòng)加載sos.dll 。。。

    <3> 使用createdump 生成dump文件

    每個(gè)dotnet版本下都有一個(gè)createdump程序,可以用它生成dump文件,具體配置文檔可以參見:

    https://github.com/dotnet/diagnostics/blob/master/documentation/debugging-coredump.md

    https://github.com/dotnet/runtime/blob/master/docs/design/coreclr/botr/xplat-minidump-generation.md#configurationpolicy

    [root@10-25-198-96 cs2]# ps -ef | grep dotnet
    root     31555 31247  0 22:28 pts/0    00:00:00 dotnet cs2.dll
    root     32112 31995  0 22:29 pts/2    00:00:00 grep --color=auto dotnet
    
    [root@10-25-198-96 cs2]# find / -name createdump
    /usr/share/dotnet/shared/Microsoft.NETCore.App/3.1.3/createdump
    
    [root@10-25-198-96 3.1.3]# ./createdump 31555  -f /lldb/test.dump
    Writing minidump with heap to file /lldb/test.dump
    Written 84692992 bytes (20677 pages) to core file
    
    [root@10-25-198-96 3.1.3]# lldb --core /lldb/test.dump
    (lldb) target create --core "/lldb/test.dump"
    Core file '/lldb/test.dump' (x86_64) was loaded.
    (lldb) clrstack -l
    OS Thread Id: 0x7b43 (1)
    00007FFDFCABF9E0 00007FAFBEBB037D cs2.Program.Main(System.String[]) [/cs2/Program.cs @ 13]
        LOCALS:
            0x00007FFDFCABF9F0 = 0x00007faf980081d8
    
    00007FFDFCABFD08 00007fb037fc0f7f [GCFrame: 00007ffdfcabfd08] 
    00007FFDFCAC01F0 00007fb037fc0f7f [GCFrame: 00007ffdfcac01f0] 
    (lldb) dumpobj 0x00007faf980081d8
    Name:        System.String
    MethodTable: 00007fafbec30f90
    EEClass:     00007fafbeb9e1b0
    Size:        44(0x2c) bytes
    File:        /usr/share/dotnet/shared/Microsoft.NETCore.App/3.1.3/System.Private.CoreLib.dll
    String:      hello world
    Fields:
                  MT    Field   Offset                 Type VT     Attr            Value Name
    00007fafbec2a0e8  400022a        8         System.Int32  1 instance               11 _stringLength
    00007fafbec26f00  400022b        c          System.Char  1 instance               68 _firstChar
    00007fafbec30f90  400022c      108        System.String  0   static 00007faf97fff360 Empty
    (lldb) 
    

    可以看到,通過(guò)lldb也可以直接打入clr內(nèi)部啦。。。

    六: 總結(jié)

    我覺得這篇文章肯定能給很多朋友節(jié)省不少的時(shí)間,想起朱一旦的那句話:有錢人的快樂,就是這么樸實(shí)無(wú)華且枯燥, 哈哈~

    本文簡(jiǎn)要介紹C/C++符號(hào)重定位的原理,并簡(jiǎn)要分析了libc對(duì)main等函數(shù)的調(diào)用順序。

    1.編譯、鏈接相關(guān)的文件

    測(cè)試代碼如下:

     /*main.c*/
     int add(int a_, int b_);
     extern int global_extern_int;
     int global_int = 3;
     
     int main()
     {
         static int a = 19;
         global_int = 5;
         int rtv = 0;
         rtv = add(global_int, global_extern_int);
         return rtv;
     }
     /*add.c*/
     int global_extern_int = 2;
     
     int add(int a_, int b_)
     {
         return a_+ b_;
     }

    編譯、鏈接(32位),

     gcc -g -fno-pie  -no-pie -m32 -c add.c
     gcc -g -fno-pie  -no-pie -m32 -c main.c
     gcc -g -fno-pie -no-pie -m32 -o main main.o add.o

    生成的應(yīng)用程序main的大小為16K。

     lyf@lyf:~/test$ ls -hl
     total 32K
     -rw-r--r-- 1 lyf lyf   74 Dec  2 10:22 add.c
     -rw-r--r-- 1 lyf lyf 2.0K Dec  2 10:42 add.o
     -rwxr-xr-x 1 lyf lyf  16K Dec  2 13:54 main
     -rw-r--r-- 1 lyf lyf  212 Dec  2 11:33 main.c
     -rw-r--r-- 1 lyf lyf 2.3K Dec  2 11:34 main.o

    大部分的現(xiàn)代操作系統(tǒng)都使用ASCII標(biāo)準(zhǔn)來(lái)表示文本字符,使用單字節(jié)的整數(shù)值來(lái)表示每個(gè)字符,如下所示,程序的源文件為ASCII文件,這種只由ASCII字符構(gòu)成的文件稱為文本文件,除了文本文件,其他的都是二進(jìn)制文件。

     lyf@lyf:~/test$ file main.c
     main.c: C source, ASCII text
     lyf@lyf:~/test$ hexdump -C ./main.c
     00000000  69 6e 74 20 61 64 64 28  69 6e 74 20 61 5f 2c 20  |int add(int a_, |
     00000010  69 6e 74 20 62 5f 29 3b  0a 65 78 74 65 72 6e 20  |int b_);.extern |
     00000020  69 6e 74 20 67 6c 6f 62  61 6c 5f 65 78 74 65 72  |int global_exter|
     00000030  6e 5f 69 6e 74 3b 0a 69  6e 74 20 67 6c 6f 62 61  |n_int;.int globa|
     00000040  6c 5f 69 6e 74 20 3d 20  33 3b 0a 0a 69 6e 74 20  |l_int = 3;..int |
     00000050  6d 61 69 6e 28 29 0a 7b  0a 20 20 20 20 73 74 61  |main().{.    sta|
     00000060  74 69 63 20 69 6e 74 20  61 20 3d 20 31 39 3b 0a  |tic int a = 19;.|
     00000070  20 20 20 20 67 6c 6f 62  61 6c 5f 69 6e 74 20 3d  |    global_int =|
     00000080  20 35 3b 0a 20 20 20 20  69 6e 74 20 72 74 76 20  | 5;.    int rtv |
     00000090  3d 20 30 3b 0a 20 20 20  20 72 74 76 20 3d 20 61  |= 0;.    rtv = a|
     000000a0  64 64 28 67 6c 6f 62 61  6c 5f 69 6e 74 2c 20 67  |dd(global_int, g|
     000000b0  6c 6f 62 61 6c 5f 65 78  74 65 72 6e 5f 69 6e 74  |lobal_extern_int|
     000000c0  29 3b 0a 20 20 20 20 72  65 74 75 72 6e 20 72 74  |);.    return rt|
     000000d0  76 3b 0a 7d                                       |v;.}|
     000000d4
     lyf@lyf:~/test$ file main.o
     main.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), with debug_info, not stripped
     lyf@lyf:~/test$ file add.o
     add.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), with debug_info, not stripped
     lyf@lyf:~/test$ file main
     main: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=5b8fb49e162dbf05605114331a1fdfb524aefbbf, for GNU/Linux 3.2.0, with debug_info, not stripped
    • .o的文件格式為ELF relocatable,可重定位的;
    • 應(yīng)用程序main的文件格式為ELF executable,可執(zhí)行的;
    • 編譯生成的.o文件以及鏈接后最終生成的main應(yīng)用程序,從本質(zhì)上來(lái)講依然是文件(Linux上遵循ELF這種文件格式);
    • 應(yīng)用程序main默認(rèn)是動(dòng)態(tài)鏈接的,大小為16K;

    默認(rèn)是動(dòng)態(tài)鏈接的,那么鏈接了什么動(dòng)態(tài)庫(kù)?發(fā)現(xiàn)是libc

     lyf@lyf:~/test$ readelf -d ./main
     
     Dynamic section at offset 0x2f14 contains 24 entries:
       Tag        Type                         Name/Value
      0x00000001 (NEEDED)                     Shared library: [libc.so.6]
      ......

    執(zhí)行應(yīng)用程序,

    lyf@lyf:~/test$ ./main
    lyf@lyf:~/test$ echo $?
    7
    • 在shell中執(zhí)行./main,shell也是一個(gè)應(yīng)用程序,當(dāng)執(zhí)行./main時(shí),會(huì)在當(dāng)前目錄下尋找名為main的可執(zhí)行程序,然后解析命令行參數(shù),本例中沒有,除此之外,還會(huì)將shell中的一些環(huán)境變量引入到main程序的執(zhí)行過(guò)程中;接著讀取main文件(二進(jìn)制文件),將ELF可執(zhí)行文件加載到內(nèi)存中(虛擬內(nèi)存,一個(gè)程序運(yùn)行時(shí)對(duì)應(yīng)一個(gè)進(jìn)程,現(xiàn)代操作系統(tǒng)進(jìn)程所操作的內(nèi)存地址為虛擬地址),如果是鏈接了動(dòng)態(tài)庫(kù),還會(huì)將動(dòng)態(tài)庫(kù)也加載到內(nèi)存中(對(duì)于PIC,Position Independent Code,只加載一份,后續(xù)介紹);
    • 執(zhí)行完成后,返回值為7,符合程序的預(yù)期;

    改main為靜態(tài)鏈接,

    lyf@lyf:~/test$ gcc -g -fno-pie -no-pie -m32 -static -o main main.o add.o

    靜態(tài)鏈接后,main的大小為731K,大了很多。

    lyf@lyf:~/test$ ls -hl
    total 748K
    -rw-r--r-- 1 lyf lyf   74 Dec  2 10:22 add.c
    -rw-r--r-- 1 lyf lyf 2.0K Dec  2 10:42 add.o
    -rwxr-xr-x 1 lyf lyf 731K Dec  2 13:51 main
    -rw-r--r-- 1 lyf lyf  212 Dec  2 11:33 main.c
    -rw-r--r-- 1 lyf lyf 2.3K Dec  2 11:34 main.o

    2.內(nèi)存中的程序

    如下圖所示,

    • 通過(guò)編譯,生成的文件為ELF Relocatable object(.o)文件;
    • 通過(guò)重定位、鏈接等,生成ELF Executable文件;
    • 鏈接器對(duì)編譯生成.o文件采用相似段合并的方法最終生成executable(其中很重要的一步就是后面要講的符號(hào)重定位)。

    ?

    如前面所介紹的,編譯鏈接后的硬盤中的main應(yīng)用程序是ELF格式的文件,通過(guò)shell執(zhí)行main后,會(huì)加載到內(nèi)存中。

    • 進(jìn)程的內(nèi)存空間中的一部分空間是使用ELF中的部分段來(lái)填充的,例如對(duì)于main的ELF中的.init,.text,.rodata等段會(huì)放在只讀區(qū),而.data,.bss等段會(huì)放在可讀可寫的區(qū)域。代碼段及只讀數(shù)據(jù)等肯定要設(shè)計(jì)成是只讀的,否則程序指令能被隨意修改會(huì)產(chǎn)生安全問題。數(shù)據(jù)區(qū)顯而易見是需要可讀寫的。
    • 對(duì)于.bss段,看過(guò)別人有個(gè)精妙的解釋,可以把它叫做Better Save Space段,主要是為了減少elf文件不必要的文件大小的增加,例如代碼中定義了一個(gè)全局4096字節(jié)長(zhǎng)度的char數(shù)組,均初始化為0,這個(gè)變量就沒必要放在數(shù)據(jù)段,然后占用4096字節(jié)都填充為0。我們只需要知道這個(gè)數(shù)據(jù)結(jié)構(gòu)的組成這些信息即可,當(dāng)后續(xù)加載到內(nèi)存中時(shí),可以再為其分配空間。

    ?

    ?

    3.什么是符號(hào)(Symbol)

    符號(hào)對(duì)應(yīng)的就是地址。變量的符號(hào)是變量的地址,函數(shù)的符號(hào)是函數(shù)的地址。鏈接過(guò)程的本質(zhì)就是把多個(gè)不同的目標(biāo)(.o)文件之間相互“粘”在一起,是解決目標(biāo)文件之間對(duì)函數(shù)和變量地址的引用。

    關(guān)于ELF文件格式的細(xì)節(jié),這里不做介紹,網(wǎng)上很多資料。應(yīng)用程序main通過(guò)編譯先有add.o和main.o,然后再鏈接生成main。因此接下來(lái)先分析.o中相關(guān)的符號(hào)(Symbol),然后再分析應(yīng)用程序main中對(duì)相關(guān)符號(hào)是如何處理的。

    對(duì)于add.o,其中定義了一個(gè)全局變量global_extern_int和add函數(shù),

    lyf@lyf:~/test$ readelf -s add.o
    
    Symbol table '.symtab' contains 10 entries:
       Num:    Value  Size Type    Bind   Vis      Ndx Name
         0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
         1: 00000000     0 FILE    LOCAL  DEFAULT  ABS add.c
         2: 00000000     0 SECTION LOCAL  DEFAULT    1 .text
         3: 00000000     0 SECTION LOCAL  DEFAULT    4 .debug_info
         4: 00000000     0 SECTION LOCAL  DEFAULT    6 .debug_abbrev
         5: 00000000     0 SECTION LOCAL  DEFAULT    9 .debug_line
         6: 00000000     0 SECTION LOCAL  DEFAULT   11 .debug_str
         7: 00000000     0 SECTION LOCAL  DEFAULT   12 .debug_line_str
         8: 00000000     4 OBJECT  GLOBAL DEFAULT    2 global_extern_int
         9: 00000000    13 FUNC    GLOBAL DEFAULT    1 add

    從上述輸出我們可以看出來(lái),全局變量global_extern_int和add函數(shù)都是符號(hào)(Symbol),且都是全局的(GLOBAL)。其中全局變量global_extern_int的Ndx為2(.data),add函數(shù)的Ndx為1(.text),對(duì)應(yīng)代碼段和數(shù)據(jù)段。函數(shù)的TYPE為FUNC,變量的TYPE為OBJECT。

    下面是add.o中包含的所有的段(Section)的信息,符號(hào)表中的Ndx對(duì)應(yīng)段表中的Nr,表示該符號(hào)屬于哪個(gè)段(Section),

    lyf@lyf:~/test$ readelf -S add.o
    There are 20 section headers, starting at offset 0x4a4:
    
    Section Headers:
      [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
      [ 0]                   NULL            00000000 000000 000000 00      0   0  0
      [ 1] .text             PROGBITS        00000000 000034 00000d 00  AX  0   0  1
      [ 2] .data             PROGBITS        00000000 000044 000004 00  WA  0   0  4
      [ 3] .bss              NOBITS          00000000 000048 000000 00  WA  0   0  1
      [ 4] .debug_info       PROGBITS        00000000 000048 00006f 00      0   0  1
      [ 5] .rel.debug_info   REL             00000000 000374 000048 08   I 17   4  4
      [ 6] .debug_abbrev     PROGBITS        00000000 0000b7 000060 00      0   0  1
      [ 7] .debug_aranges    PROGBITS        00000000 000117 000020 00      0   0  1
      [ 8] .rel.debug_a[...] REL             00000000 0003bc 000010 08   I 17   7  4
      [ 9] .debug_line       PROGBITS        00000000 000137 00004b 00      0   0  1
      [10] .rel.debug_line   REL             00000000 0003cc 000020 08   I 17   9  4
      [11] .debug_str        PROGBITS        00000000 000182 00009c 01  MS  0   0  1
      [12] .debug_line_str   PROGBITS        00000000 00021e 000030 01  MS  0   0  1
      [13] .comment          PROGBITS        00000000 00024e 00002c 01  MS  0   0  1
      [14] .note.GNU-stack   PROGBITS        00000000 00027a 000000 00      0   0  1
      [15] .eh_frame         PROGBITS        00000000 00027c 000038 00   A  0   0  4
      [16] .rel.eh_frame     REL             00000000 0003ec 000008 08   I 17  15  4
      [17] .symtab           SYMTAB          00000000 0002b4 0000a0 10     18   8  4
      [18] .strtab           STRTAB          00000000 000354 00001d 00      0   0  1
      [19] .shstrtab         STRTAB          00000000 0003f4 0000af 00      0   0  1
    Key to Flags:
      W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
      L (link order), O (extra OS processing required), G (group), T (TLS),
      C (compressed), x (unknown), o (OS specific), E (exclude),
      D (mbind), p (processor specific)

    對(duì)于main.o而言,引用了add.o中的函數(shù)和全局變量,同時(shí)自己定義了全局變量global_int及局部變量rtv,那么main.o的符號(hào)表,

    lyf@lyf:~/test$ readelf -s main.o
    
    Symbol table '.symtab' contains 13 entries:
       Num:    Value  Size Type    Bind   Vis      Ndx Name
         0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
         1: 00000000     0 FILE    LOCAL  DEFAULT  ABS main.c
         2: 00000000     0 SECTION LOCAL  DEFAULT    1 .text
         3: 00000004     4 OBJECT  LOCAL  DEFAULT    3 a.0
         4: 00000000     0 SECTION LOCAL  DEFAULT    5 .debug_info
         5: 00000000     0 SECTION LOCAL  DEFAULT    7 .debug_abbrev
         6: 00000000     0 SECTION LOCAL  DEFAULT   10 .debug_line
         7: 00000000     0 SECTION LOCAL  DEFAULT   12 .debug_str
         8: 00000000     0 SECTION LOCAL  DEFAULT   13 .debug_line_str
         9: 00000000     4 OBJECT  GLOBAL DEFAULT    3 global_int
        10: 00000000    72 FUNC    GLOBAL DEFAULT    1 main
        11: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND global_extern_int
        12: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND add

    如上所示,

    • 局部變量(rtv)不是符號(hào),并不在符號(hào)表中;
    • 靜態(tài)變量,全局變量,函數(shù)都是符號(hào),靜態(tài)變量的符號(hào)的作用域是本地LOCAL;
    • global_extern_int和add引用了add.o中的符號(hào),因此其類型為NOTYPE,因?yàn)樵阪溄忧斑€不知道具體的類型。

    4.符號(hào)的重定位

    main.o中對(duì)符號(hào)的引用是如何進(jìn)行的?也就是如何獲取到所需要的符號(hào)的真實(shí)地址呢?

    首先,因?yàn)閙ain.o要使用外部的符號(hào)(add.o中的),因此在main.o中有一個(gè)重定位段(.rel.text),告訴鏈接器該如何去做符號(hào)重定位。下面重定位段中的Offset指的是相對(duì)于.text段起始位置的偏移量。

    lyf@lyf:~/test$ readelf -r ./main.o
    
    Relocation section '.rel.text' at offset 0x484 contains 4 entries:
     Offset     Info    Type            Sym.Value  Sym. Name
    00000013  00000901 R_386_32          00000000   global_int
    00000024  00000b01 R_386_32          00000000   global_extern_int
    00000029  00000901 R_386_32          00000000   global_int
    00000033  00000c02 R_386_PC32        00000000   add
    ......
    • 對(duì)于global_int,需要在.text段中0x13和0x29的位置去做重定位,重定位的方式是R_386_32;
    • 對(duì)于global_extern_int,需要在.text段中0x24的位置去做重定位,重定位的方式是R_386_32;
    • 對(duì)于add函數(shù),需要在.text段中0x33的位置去做重定位,重定位的方式是R_386_PC32;

    Name

    Value

    Field

    Calculation

    R_386_NONE

    0

    None

    None

    R_386_32

    2

    dword

    S + A

    R_386_PC32

    1

    dword

    S + A – P

    R_386_GOT32

    3

    dword

    G + A

    R_386_PLT32

    4

    dword

    L + A – P

    R_386_COPY

    5

    None

    Value is copied directly from shared object

    R_386_GLOB_DAT

    6

    dword

    S

    R_386_JMP_SLOT

    7

    dword

    S

    R_386_RELATIVE

    8

    dword

    B + A

    R_386_GOTOFF

    9

    dword

    S + A – GOT

    R_386_GOTPC

    10

    dword

    GOT + A – P

    R_386_32PLT

    11

    dword

    L + A

    R_386_16

    20

    word

    S + A

    R_386_PC16

    21

    word

    S + A – P

    R_386_8

    22

    byte

    S + A

    R_386_PC8

    23

    byte

    S + A – P

    R_386_SIZE32

    38

    dword

    z + A

    其中,R_386_32和R_386_PC32的重定位計(jì)算方式中,

    • A為保存在修正位置的值;
    • S為符號(hào)的實(shí)際地址,這個(gè)地址在鏈接前是沒有的,只有通過(guò)鏈接,將所有的.o的相似段進(jìn)行合并,生成可執(zhí)行文件,此時(shí)所有符號(hào)的地址都已經(jīng)確定好了(此時(shí)所有符號(hào),指令的地址都是真實(shí)的,也就是對(duì)應(yīng)運(yùn)行時(shí)進(jìn)程的虛擬地址)。但是這個(gè)時(shí)候合并的很多.o的.text代碼段中的部分符號(hào)地址依然不是最終的確定地址,需要去用上面的公式去做重定位。是個(gè)反過(guò)來(lái)的過(guò)程,先把所有符號(hào)的地址都定下來(lái)后,然后再去修改.text代碼段中部分的符號(hào)地址,然后才生成可以正確執(zhí)行的可執(zhí)行程序。
    • P為被修正的位置,后面通過(guò)例子解釋會(huì)很容易理解。

    下面是main.o中對(duì)應(yīng)代碼段的反匯編,

    lyf@lyf:~/test$ objdump -drS -Mintel ./main.o
    
    ./main.o:     file format elf32-i386
    
    
    Disassembly of section .text:
    
    00000000 <main>:
    int add(int a_, int b_);
    extern int global_extern_int;
    int global_int = 3;
    
    int main()
    {
       0:   8d 4c 24 04             lea    ecx,[esp+0x4]
       4:   83 e4 f0                and    esp,0xfffffff0
       7:   ff 71 fc                push   DWORD PTR [ecx-0x4]
       a:   55                      push   ebp
       b:   89 e5                   mov    ebp,esp
       d:   51                      push   ecx
       e:   83 ec 14                sub    esp,0x14
        static int a = 19;
        global_int = 5;
      11:   c7 05 00 00 00 00 05    mov    DWORD PTR ds:0x0,0x5
      18:   00 00 00
                            13: R_386_32    global_int
        int rtv = 0;
      1b:   c7 45 f4 00 00 00 00    mov    DWORD PTR [ebp-0xc],0x0
        rtv = add(global_int, global_extern_int);
      22:   8b 15 00 00 00 00       mov    edx,DWORD PTR ds:0x0
                            24: R_386_32    global_extern_int
      28:   a1 00 00 00 00          mov    eax,ds:0x0
                            29: R_386_32    global_int
      2d:   83 ec 08                sub    esp,0x8
      30:   52                      push   edx
      31:   50                      push   eax
      32:   e8 fc ff ff ff          call   33 <main+0x33>
                            33: R_386_PC32  add
      37:   83 c4 10                add    esp,0x10
      3a:   89 45 f4                mov    DWORD PTR [ebp-0xc],eax
        return rtv;
      3d:   8b 45 f4                mov    eax,DWORD PTR [ebp-0xc]
      40:   8b 4d fc                mov    ecx,DWORD PTR [ebp-0x4]
      43:   c9                      leave
      44:   8d 61 fc                lea    esp,[ecx-0x4]
      47:   c3                      ret
    • 結(jié)合main.o的重定向表.rel.text,在.text偏移0x13的位置上需要去做個(gè)R_386_32類型的重定向。也就是c7 05 00 00 00 00 05,對(duì)應(yīng)的代碼為global_int=5,0x13對(duì)應(yīng)的是4個(gè)字節(jié)的global_int對(duì)應(yīng)的地址,但是此時(shí)是00 00 00 00,所以此時(shí)對(duì)應(yīng)的A為0;
    • 在.text偏移0x33的位置上需要去做個(gè)R_386_PC32類型的重定向,也就是e8 fc ff ff ff,其中0xe8是操作碼,查找INTEL IA-32指令手冊(cè),這條指令是一個(gè)近址相對(duì)位移調(diào)用指令,在e8后面跟著的4個(gè)字節(jié)是被調(diào)用函數(shù)相對(duì)于調(diào)用指令下一條指令的偏移量。小端,fc ff ff ff對(duì)應(yīng)ff ff ff fc,對(duì)應(yīng)-4,調(diào)用指令下一條指令的地址為0x37,0x37-4=0x33,被調(diào)用函數(shù)的地址是0x33,又回到了原地?此時(shí)A的值為-4;

    接下來(lái),看看粘和后的main應(yīng)用程序中對(duì)應(yīng)符號(hào)的地址,對(duì)應(yīng)公式中對(duì)應(yīng)的S,

    lyf@lyf:~/test$ readelf -s ./main
    
    Symbol table '.dynsym' contains 4 entries:
       Num:    Value  Size Type    Bind   Vis      Ndx Name
         0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
         1: 00000000     0 FUNC    GLOBAL DEFAULT  UND _[...]@GLIBC_2.34 (2)
         2: 00000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
         3: 0804a004     4 OBJECT  GLOBAL DEFAULT   15 _IO_stdin_used
    
    Symbol table '.symtab' contains 40 entries:
       Num:    Value  Size Type    Bind   Vis      Ndx Name
         0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
         1: 00000000     0 FILE    LOCAL  DEFAULT  ABS crt1.o
         2: 080481cc    32 OBJECT  LOCAL  DEFAULT    3 __abi_tag
         3: 00000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
         4: 080490b0     0 FUNC    LOCAL  DEFAULT   13 deregister_tm_clones
         5: 080490f0     0 FUNC    LOCAL  DEFAULT   13 register_tm_clones
         6: 08049130     0 FUNC    LOCAL  DEFAULT   13 __do_global_dtors_aux
         7: 0804c024     1 OBJECT  LOCAL  DEFAULT   24 completed.0
         8: 0804bf10     0 OBJECT  LOCAL  DEFAULT   19 __do_global_dtor[...]
         9: 08049160     0 FUNC    LOCAL  DEFAULT   13 frame_dummy
        10: 0804bf0c     0 OBJECT  LOCAL  DEFAULT   18 __frame_dummy_in[...]
        11: 00000000     0 FILE    LOCAL  DEFAULT  ABS main.c
        12: 0804c01c     4 OBJECT  LOCAL  DEFAULT   23 a.0
        13: 00000000     0 FILE    LOCAL  DEFAULT  ABS add.c
        14: 00000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
        15: 0804a0ec     0 OBJECT  LOCAL  DEFAULT   17 __FRAME_END__
        16: 00000000     0 FILE    LOCAL  DEFAULT  ABS
        17: 0804bf14     0 OBJECT  LOCAL  DEFAULT   20 _DYNAMIC
        18: 0804a008     0 NOTYPE  LOCAL  DEFAULT   16 __GNU_EH_FRAME_HDR
        19: 0804c000     0 OBJECT  LOCAL  DEFAULT   22 _GLOBAL_OFFSET_TABLE_
        20: 0804c020     4 OBJECT  GLOBAL DEFAULT   23 global_extern_int
        21: 00000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_mai[...]
        22: 080490a0     4 FUNC    GLOBAL HIDDEN    13 __x86.get_pc_thunk.bx
        23: 0804c010     0 NOTYPE  WEAK   DEFAULT   23 data_start
        24: 080491ae    13 FUNC    GLOBAL DEFAULT   13 add
        25: 0804c018     4 OBJECT  GLOBAL DEFAULT   23 global_int
        26: 0804c024     0 NOTYPE  GLOBAL DEFAULT   23 _edata
        27: 080491bc     0 FUNC    GLOBAL HIDDEN    14 _fini
        28: 0804c010     0 NOTYPE  GLOBAL DEFAULT   23 __data_start
        29: 00000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
        30: 0804c014     0 OBJECT  GLOBAL HIDDEN    23 __dso_handle
        31: 0804a004     4 OBJECT  GLOBAL DEFAULT   15 _IO_stdin_used
        32: 0804c028     0 NOTYPE  GLOBAL DEFAULT   24 _end
        33: 08049090     5 FUNC    GLOBAL HIDDEN    13 _dl_relocate_sta[...]
        34: 08049050    49 FUNC    GLOBAL DEFAULT   13 _start
        35: 0804a000     4 OBJECT  GLOBAL DEFAULT   15 _fp_hw
        36: 0804c024     0 NOTYPE  GLOBAL DEFAULT   24 __bss_start
        37: 08049166    72 FUNC    GLOBAL DEFAULT   13 main
        38: 0804c024     0 OBJECT  GLOBAL HIDDEN    23 __TMC_END__
        39: 08049000     0 FUNC    GLOBAL HIDDEN    11 _init
    • main的地址為0x08049166,add函數(shù)的地址為0x080491ae,global_extern_int的地址為0x0804c020,global_int的地址為0x0804c018;
    • main.o的在.text偏移0x13的位置上的R_386_32類型的重定向,global_int對(duì)應(yīng)的真實(shí)地址為0x0804c018,S=0x0804c018,A為0,則main.o中.text的0x13的位置上的重定位的結(jié)果為S+A=0x0804c018;
    • main.o在.text偏移0x33的位置上的R_386_PC32類型的重定向,add的實(shí)際地址為0x080491ae,則S=0x080491ae,A為-4,P為修正處的位置即main+0x33,即0x08049166+0x33=0x8049199,則S+A-P=0x080491ae+(-4)-0x8049199=0x11,則重定位后的結(jié)果為0x11;
    • 在main中還有一些其他的函數(shù)符號(hào),例如,__libc_start_main@GLIBC_2.34 , _init ,_fini,可以把他們理解成圖一中的System code,其實(shí)雖然main函數(shù)是C/C++的入口函數(shù),但是它也是被其他的system code去調(diào)用,下面從main的反匯編代碼中也能看出來(lái)。

    下面來(lái)確認(rèn)下,最終重定位的結(jié)果是否正確,查看應(yīng)用程序main的反匯編代碼,

    lyf@lyf:~/test$ objdump -d -Mintel ./main
    
    ./main:     file format elf32-i386
    
    
    Disassembly of section .init:
    
    08049000 <_init>:
     8049000:       f3 0f 1e fb             endbr32
     8049004:       53                      push   ebx
     8049005:       83 ec 08                sub    esp,0x8
     8049008:       e8 93 00 00 00          call   80490a0 <__x86.get_pc_thunk.bx>
     804900d:       81 c3 f3 2f 00 00       add    ebx,0x2ff3
     8049013:       8b 83 fc ff ff ff       mov    eax,DWORD PTR [ebx-0x4]
     8049019:       85 c0                   test   eax,eax
     804901b:       74 02                   je     804901f <_init+0x1f>
     804901d:       ff d0                   call   eax
     804901f:       83 c4 08                add    esp,0x8
     8049022:       5b                      pop    ebx
     8049023:       c3                      ret
    
    Disassembly of section .plt:
    
    08049030 <__libc_start_main@plt-0x10>:
     8049030:       ff 35 04 c0 04 08       push   DWORD PTR ds:0x804c004
     8049036:       ff 25 08 c0 04 08       jmp    DWORD PTR ds:0x804c008
     804903c:       00 00                   add    BYTE PTR [eax],al
            ...
    
    08049040 <__libc_start_main@plt>:
     8049040:       ff 25 0c c0 04 08       jmp    DWORD PTR ds:0x804c00c
     8049046:       68 00 00 00 00          push   0x0
     804904b:       e9 e0 ff ff ff          jmp    8049030 <_init+0x30>
    
    Disassembly of section .text:
    
    08049050 <_start>:
     8049050:       f3 0f 1e fb             endbr32
     8049054:       31 ed                   xor    ebp,ebp
     8049056:       5e                      pop    esi
     8049057:       89 e1                   mov    ecx,esp
     8049059:       83 e4 f0                and    esp,0xfffffff0
     804905c:       50                      push   eax
     804905d:       54                      push   esp
     804905e:       52                      push   edx
     804905f:       e8 19 00 00 00          call   804907d <_start+0x2d>
     8049064:       81 c3 9c 2f 00 00       add    ebx,0x2f9c
     804906a:       6a 00                   push   0x0
     804906c:       6a 00                   push   0x0
     804906e:       51                      push   ecx
     804906f:       56                      push   esi
     8049070:       c7 c0 66 91 04 08       mov    eax,0x8049166
     8049076:       50                      push   eax
     8049077:       e8 c4 ff ff ff          call   8049040 <__libc_start_main@plt>
     804907c:       f4                      hlt
     804907d:       8b 1c 24                mov    ebx,DWORD PTR [esp]
     8049080:       c3                      ret
     8049081:       66 90                   xchg   ax,ax
     8049083:       66 90                   xchg   ax,ax
     8049085:       66 90                   xchg   ax,ax
     8049087:       66 90                   xchg   ax,ax
     8049089:       66 90                   xchg   ax,ax
     804908b:       66 90                   xchg   ax,ax
     804908d:       66 90                   xchg   ax,ax
     804908f:       90                      nop
    
    
    
    08049166 <main>:
     8049166:       8d 4c 24 04             lea    ecx,[esp+0x4]
     804916a:       83 e4 f0                and    esp,0xfffffff0
     804916d:       ff 71 fc                push   DWORD PTR [ecx-0x4]
     8049170:       55                      push   ebp
     8049171:       89 e5                   mov    ebp,esp
     8049173:       51                      push   ecx
     8049174:       83 ec 14                sub    esp,0x14
     8049177:       c7 05 18 c0 04 08 05    mov    DWORD PTR ds:0x804c018,0x5
     804917e:       00 00 00
     8049181:       c7 45 f4 00 00 00 00    mov    DWORD PTR [ebp-0xc],0x0
     8049188:       8b 15 20 c0 04 08       mov    edx,DWORD PTR ds:0x804c020
     804918e:       a1 18 c0 04 08          mov    eax,ds:0x804c018
     8049193:       83 ec 08                sub    esp,0x8
     8049196:       52                      push   edx
     8049197:       50                      push   eax
     8049198:       e8 11 00 00 00          call   80491ae <add>
     804919d:       83 c4 10                add    esp,0x10
     80491a0:       89 45 f4                mov    DWORD PTR [ebp-0xc],eax
     80491a3:       8b 45 f4                mov    eax,DWORD PTR [ebp-0xc]
     80491a6:       8b 4d fc                mov    ecx,DWORD PTR [ebp-0x4]
     80491a9:       c9                      leave
     80491aa:       8d 61 fc                lea    esp,[ecx-0x4]
     80491ad:       c3                      ret
    
    080491ae <add>:
     80491ae:       55                      push   ebp
     80491af:       89 e5                   mov    ebp,esp
     80491b1:       8b 55 08                mov    edx,DWORD PTR [ebp+0x8]
     80491b4:       8b 45 0c                mov    eax,DWORD PTR [ebp+0xc]
     80491b7:       01 d0                   add    eax,edx
     80491b9:       5d                      pop    ebp
     80491ba:       c3                      ret
    
    Disassembly of section .fini:
    
    080491bc <_fini>:
     80491bc:       f3 0f 1e fb             endbr32
     80491c0:       53                      push   ebx
     80491c1:       83 ec 08                sub    esp,0x8
     80491c4:       e8 d7 fe ff ff          call   80490a0 <__x86.get_pc_thunk.bx>
     80491c9:       81 c3 37 2e 00 00       add    ebx,0x2e37
     80491cf:       83 c4 08                add    esp,0x8
     80491d2:       5b                      pop    ebx
     80491d3:       c3                      ret
    
    • 8049177行,修正后的地址為0x804c018,和上述計(jì)算結(jié)果相同;
    • 8049198行,修正后的結(jié)果為e8 11 00 00 00,小端,即0x11,和上述計(jì)算結(jié)果相同;

    結(jié)合下圖和main的反匯編代碼,其中__libc_start_main的函數(shù)簽名如下所示,main函數(shù)是被其調(diào)用的,

    int __libc_start_main(int *(main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end));

    • _start是真正的函數(shù)入口,會(huì)去調(diào)用__libc_start_main;
    • __libc_start_main會(huì)去調(diào)用__init,main,__fini等函數(shù);
    • 8049070: c7 c0 66 91 04 08 mov eax,0x8049166將main函數(shù)的指針(0x8049166)放入寄存器,入棧,8049077: e8 c4 ff ff ff call 8049040 <__libc_start_main@plt>調(diào)用__libc_start_main,接著就開始執(zhí)行用戶層代碼;
    • 關(guān)于__libc_start_main@plt后面在介紹動(dòng)態(tài)庫(kù)和PIC(地址無(wú)關(guān)代碼)時(shí)會(huì)介紹(本文main默認(rèn)動(dòng)態(tài)鏈接了libc庫(kù)),這里可以理解成調(diào)用__libc_start_main。
網(wǎng)站首頁(yè)   |    關(guān)于我們   |    公司新聞   |    產(chǎn)品方案   |    用戶案例   |    售后服務(wù)   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區(qū)    電話:010-     郵箱:@126.com

備案號(hào):冀ICP備2024067069號(hào)-3 北京科技有限公司版權(quán)所有