新聞中心

        EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 匯編技術(shù)內(nèi)幕(6)

        匯編技術(shù)內(nèi)幕(6)

        作者: 時(shí)間:2016-11-24 來(lái)源:網(wǎng)絡(luò) 收藏
        問(wèn)題:全局變量全局常量在進(jìn)程地址空間的位置?

        顯然,根據(jù)前面的敘述,全局變量在用戶的數(shù)據(jù)段,那么全局常量呢,是數(shù)據(jù)段嗎?
        同樣的,可以利用mdb將test5進(jìn)程掛起,然后用pmap命令求證一下:
        # mdb test5
        Loading modules: [ libc.so.1 ]
        > ::sysbp _exit ; 在系統(tǒng)調(diào)用_exit處設(shè)置斷點(diǎn)
        > :r ; 運(yùn)行程序
        mdb: stop on entry to _exit
        mdb: target stopped at:
        libc.so.1`exit+0x2b: jae +0x15
        >

        本文引用地址:http://www.104case.com/article/201611/320804.htm

        此時(shí),程序運(yùn)行后在_exit處掛起,可以利用pmap在另一個(gè)終端內(nèi)查看test5進(jìn)程的地址空間了:
        # ps -ef | grep test5
        root 1387 1386 0 02:23:53 pts/1 0:00 test5
        root 1399 1390 0 02:25:03 pts/3 0:00 grep test5
        root 1386 1338 0 02:23:41 pts/1 0:00 mdb test5
        # pmap -F 1387 ; 用pmap強(qiáng)制查看
        1387: test5
        08044000 16K rwx-- [ stack ] ; test5的stack
        08050000 4K r-x-- /export/home/asm/L3/test5 ; test5的代碼段,起始地址為0x08050000
        08060000 4K rwx-- /export/home/asm/L3/test5 ; test5的數(shù)據(jù)段,起始地址為0x08060000
        DDAC0000 628K r-x-- /usr/lib/libc.so.1
        DDB6D000 24K rwx-- /usr/lib/libc.so.1
        DDB73000 4K rwx-- /usr/lib/libc.so.1
        DDB80000 4K r-x-- /usr/lib/libdl.so.1
        DDB90000 292K r-x-- /usr/lib/ld.so.1
        DDBE9000 16K rwx-- /usr/lib/ld.so.1
        DDBED000 8K rwx-- /usr/lib/ld.so.1
        total 1000K
        可以看到,由于test5程序沒(méi)有使用malloc來(lái)申請(qǐng)內(nèi)存,所以沒(méi)有heap的映射
        前面用mdb觀察過(guò)這些全局變量和常量的初始化值,它們的地址分別是:
        全局變量i,j,k:
        0x8060904起始的12字節(jié)
        全局變量l,m,n:
        0x8060948起始的12字節(jié)
        全局常量o,p,q:
        0x8050808起始的12字節(jié)
        顯然,根據(jù)這些變量的地址,我們可以初步判斷出這些變量屬于哪個(gè)段:
        由于test5數(shù)據(jù)段起始地址為0x08060000,我們得出結(jié)論:全局變量i,j,k,l,m,n屬于數(shù)據(jù)段
        而test5代碼段的起始地址為0x08050000,我們得出結(jié)論:全局常量o,p,q屬于代碼段
        得出這個(gè)結(jié)論的確有點(diǎn)讓人意外:全局常量竟然在代碼段。
        卻又似乎在情理之中:數(shù)據(jù)段內(nèi)存映射后的屬性是r/w/x,而常量要求是只讀屬性,所以在代碼段(r-x)就合情合理了。

        問(wèn)題:為什么這些全局變量地址不是連續(xù)的?

        很容易注意到,全局變量i,j,k和l,m,n以及全局常量o,p,q是連續(xù)聲明的,但地址實(shí)際上并不連續(xù),而是在3段連續(xù)12字節(jié)的地址上。
        當(dāng)然,全局常量屬于代碼段,所以地址和全局變量是分開(kāi)的;那么,為什么全局變量也并非連續(xù)呢?

        概念:ELF(Executable and Linking Format) 可執(zhí)行連接格式

        ELF格式是UNIX系統(tǒng)實(shí)驗(yàn)室(USL)作為應(yīng)用程序二進(jìn)制接口(Application Binary Interface,ABI)而開(kāi)發(fā)和發(fā)布的。
        目前,ELF格式是Unix/Linux平臺(tái)上應(yīng)用最廣泛的二進(jìn)制工業(yè)標(biāo)準(zhǔn)之一

        下圖從不同視角給出了ELF文件的一般格式:

        Linking 視角 Execution 視角
        ============ ==============
        ELF header ELF header
        Program header table (optional) Program header table
        Section 1 Segment 1
        ... Segment 2
        Section n ...
        Section header table Section header table (optional)

        圖 3-2 ELF文件格式 摘自 EXECUTABLE AND LINKABLE FORMAT (ELF)

        可以根據(jù)test5 ELF文件的Program header table和Section header table中文件偏移量的信息描繪出test5的內(nèi)容:

        entry name 起始文件偏移+實(shí)際大小=下個(gè)entry起始偏移
        -------------------------------------------------------
        ELF header 0x0+0x34=0x34
        Program header 0x34+0xa0=0xd4
        Section 1 .interp 0xd4+0x11=0xe5
        000 0xe5+0x3=0xe8
        Section 2 .hash 0xe8+0x104=0x1ec
        Section 3 .dynsym 0x1ec+0x200=0x3ec
        Section 4 .dynstr 0x3ec+0x11a=0x506
        00 0x506+0x2=0x508
        Section 5 .SUNW_version 0x508+0x20=0x528
        Section 6 .rel.got 0x528+0x18=0x540
        Section 7 .rel.bss 0x540+0x8=0x548
        Section 8 .rel.plt 0x548+0x38=0x580
        Section 9 .plt 0x580+0x80=0x600
        Section 10 .text 0x600+0x1ec=0x7ec
        Section 11 .init 0x7ec+0xd=0x7f9
        Section 12 .fini 0x7f9+0x8=0x801
        000 0x801+0x3=0x804
        Section 13 .rodata 0x804+0x10=0x814
        Section 14 .got 0x814+0x34=0x848
        Section 15 .dynamic 0x848+0xb8=900
        Section 16 .data 0x900+0x10=0x910
        Section 17 .ctors 0x910+0x8=0x918
        Section 18 .dtors 0x918+0x8=0x920
        Section 19 .eh_frame 0x920+0x4=0x924
        Section 20 .jcr 0x924+0x4=0x928
        Section 21 .data.rel.local 0x928+0x4=0x92c
        Section 22 .bss 0x92c+0x0=0x958
        Section 23 .symtab 0x92c+0x540=0xe6c
        Section 24 .strtab 0xe6c+0x20b=1077
        Section 25 .comment 0x1077+0x24d=0x12c4
        Section 26 .stab.index 0x12c4+0x24=0x12e8
        Section 27 .shstrtab 0x12e8+0xdc=0x13c4
        Section 28 .stab.indexstr 0x13c4+0x1c0=0x1584
        Section header table 0x1584+0x488=0x1a0c ; 29x40=1160=0x488 這是根據(jù)Elf header的信息算得的
        ------------------------------------------------------
        圖 3-3 test5的ELF文件格式

        # ls -al test5
        -rwxr-xr-x 1 root other 6668 2004-12-19 06:56 test5

        可以看到test5的大小是0x1a0c字節(jié),即6688字節(jié)。
        可以看到,.bss section用于保存未初始化的全局變量,因此不占據(jù)ELF文件空間;
        ELF文件裝入時(shí),會(huì)按照Section header table 22中的.bss的相關(guān)屬性,為.bss映射相應(yīng)大小的內(nèi)存空間,并初始化為0


        ELF文件的Program header table描述了如何將ELF裝入內(nèi)存:
        Program Header 2 描述了用戶代碼段的起始地址和大小: 0x8050000+0x814=0x8050814
        Program Header 3 描述了用戶數(shù)據(jù)段的起始地址和大小: 0x8060814+0x144=0x8060958



        評(píng)論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 舟曲县| 祁阳县| 鄂托克旗| 霍州市| 祥云县| 洱源县| 新河县| 赤水市| 安顺市| 资阳市| 衡南县| 宜城市| 临江市| 波密县| 南阳市| 昌黎县| 治多县| 鲁山县| 连山| 华容县| 通道| 藁城市| 江山市| 高陵县| 锡林郭勒盟| 大荔县| 甘德县| 侯马市| 运城市| 莱西市| 大丰市| 丹寨县| 石景山区| 闸北区| 嵊州市| 南华县| 襄城县| 垦利县| 天津市| 西乡县| 林州市|