2015年1月2日 星期五

[Assembly] Relocation,以靜態聯結為範例

C code

/* a.c */
extern int shared;

int main()
{
    int a = 100;
    swap( &a, &shared );
}

/* b.c */
int shared = 1;

void swap( int* a, int* b )
{
    *a ^= *b ^= *a ^= *b;
}


Object file


$ gcc -c a.c b.c
$ ld a.o b.o -e main -o ab
$ objdump -h ab


$ objdump -t ab

Assembly code


 a.o 有兩個符號需要重新定位,shared 與 swap,其位置分別位於 0x15 與 0x21處。此處
  • R_386_32 表示 絕對定址修正(位址長度為 32bit,4 bytes)
  • R_386_PC32 表示 相對定址修正

    shared 與 swap 對應的程式碼對應如下
    • extern int shared;  --> line 11,暫時位址為 "0x00000000"
    • swap( &a, &shared ); --> line 20,暫時位址為 "0xFFFFFFFC"

    參考下述執行檔 ab,已經分別針對 shared 與 swap 重新定位
    • extern int shared; ,位址由 "0x00000000" 改為 "0x080490f8"
    • swap( &a, &shared ); ,位址由 "0xFFFFFFFC"  改為 "0x00000003",表示 swap函數的實際位址為  下個指令位址 + Offset = 0x080450b9 + 0x00000003 = 0x008480bc


    參考資料:
    1. 程式設計師的自我修養
    2. https://github.com/samuelololol/self-knowledgeable/tree/master/4