2015-12-02 43 views
0

我需要可執行文件中的代碼段的位置(開始和結束地址)。我試圖用兩個虛擬功能:獲取可執行文件中的函數位置

void begin_address(){} 
void f(){ 
    ... 
} 
void end_address(){} 

... 

printf("Function length: %td\n", (intptr_t)end_address - (intptr_t)begin_address); 

的問題是,當使用-O4優化與gcc我得到了一個負長度。看起來這不適用於優化。

我編f到組裝,並嘗試以下操作:

__asm__(
"func_begin:" 
"movq $10, %rax;" 
"movq $20, %rbx;" 
"addq %rbx, %rax;" 
"func_end:" 
); 

extern unsigned char* func_begin; 
extern unsigned char* func_end; 

int main(){ 
    printf("Function begin and end address: %p\t%p\n", func_begin, func_end); 
    printf("Function length: %td\n", (intptr_t)func_end - (intptr_t)func_begin); 
} 

的問題是,即使沒有優化我收到一些奇怪的輸出:

Function begin and end address: 0x480000000ac0c748 0xf5158b48e5894855 
Function length: -5974716185612615411 

我怎樣才能得到的位置可執行文件中的函數?我的第二個問題是,是否將此地址稱爲const char*是否安全。如果有差異,我對32位和64位解決方案感興趣。

+2

在第二個例子中,你想要使用'func_begin'(func_begin的地址)而不是'func_begin'(它的值)。 – immibis

+0

我很驚訝你沒有得到零的第一種方法。 gcc將優化相同的功能來共享一個定義(兩個符號指的是相同的地址)。這兩個函數都是空的,所以應該編譯成一個'ret'。你應該在http://gcc.godbolt.org/上試試看看編譯器是怎麼產生的(使用高亮和格式化)。 –

回答

0

如果您有一個可行的選擇,告訴GCC與-O0,而不是編譯所需的部件:

#include <stdio.h> 
#include <stdint.h> 

void __attribute__((optimize("O0"))) func_begin(){} 
void __attribute__((optimize("O0"))) f(){ 
    return; 
} 
void __attribute__((optimize("O0"))) func_end(){} 

int main() 
{ 
    printf("Function begin and end address: %p\t%p\n", func_begin, func_end); 
    printf("Function length: %td\n", (uintptr_t)func_end - (uintptr_t)func_begin); 
} 

我不知道是否需要f()__attribute__((optimize("O0")))

1

如果要查看函數佔用二進制文件的字節數,可以使用objdump反彙編二進制文件以查看函數的第一個ip和最後一個ip。或者你可以打印$ ebp - $ esp,如果你想知道一個函數在堆棧上有多少空間。

0

我不知道GCC,但在某些微軟編譯器或Visual Studio的某些版本的情況下,如果您以調試模式構建,它會爲函數條目創建一個跳轉表,然後跳轉到實際功能。在發佈模式下,它通常不使用跳轉表。

我以爲大多數連接器都有一個映射輸出選項,至少可以顯示函數的偏移量。

你可以使用一個彙編指令,你可以搜索:

 movel $12345678,eax  ;search for this instruction 

這與Microsoft C/C++ 4.1,VS2005和VS2010發佈工作建立:

#include <stdio.h> 

void swap(char **a, char **b){ 
    char *temp = *a; 
    *a = *b; 
    *b = temp; 
} 

void sortLine(char *a[], int size){ 
    int i, j; 
    for (i = 0; i < size; i++){ 
     for (j = i + 1; j < size; j++){ 
      if(memcmp(a[i], a[j], 80) > 0){ 
       swap(&a[i], &a[j]); 
      } 
     } 
    } 
} 

int main(int argc, char **argv) 
{ 
void (*pswap)(char **a, char **b) = swap; 
void (*psortLine)(char *a[], int size) = sortLine; 
char *pfun1 = (void *) pswap; 
char *pfun2 = (void *) psortLine; 

    printf("%p %p %x\n", pfun1, pfun2, pfun2-pfun1); 

    return(0); 
}