天天看點

elf 取路徑_利用libbfd擷取elf可執行檔案的section(節)及symbol(符号)資訊

一. 安裝bfd庫

libbfd(Binary File Descriptor library是binutils中附帶的一個C庫。

從 http://ftp.gnu.org/gnu/binutils 下載下傳binutils。

我們這裡下載下傳binutils-2.23.2.tar.gz

下載下傳後,解壓安裝libbfd。方法如下:

tar -xzf binutils-2.23.2.tar.gz

cd binutils-2.23.2/bfd

./configure

make

make install

安裝完成後,可以看到有如下檔案生成。

/usr/local/include/bfd.h

/usr/local/lib/libbfd.a

二. 使用bfd庫需要注意的地方

1. 頭檔案包含

程式使用bfd,需要包含bfd.h頭檔案。

但是,在包含bfd.h之前,還需要包含config.h。

即代碼中需要有如下形式的檔案包含:

#include "config.h"

#include

那麼這個config.h是什麼東東呢?他不是系統的頭檔案,也不是bfd庫的頭檔案,而是應用程式自己的頭檔案。

然而使用者可能會感到奇怪,我的應用程式源碼中并不存在這個config.h檔案。那是因為你開發應用時,沒有采用GNU autotools。

采用GNU autotools的項目,在編譯前一般都會執行一下configure腳本,生成Makefile及config.h檔案。

那麼,對于沒有使用GNU autotools的應用,怎麼解決呢?本文這裡提供一個簡單的config.h檔案。

這個檔案的内容,相當于是使用GNU autotools開發一個hello world項目而得到的config.h。

#define PACKAGE "hello"

#define PACKAGE_BUGREPORT "[email protected]"

#define PACKAGE_NAME "hello"

#define PACKAGE_STRING "hello 1.0"

#define PACKAGE_TARNAME "hello"

#define PACKAGE_URL ""

#define PACKAGE_VERSION "1.0"

#define VERSION "1.0"

2. 連結

需要帶上這幾個庫:bfd iberty  dl z

例如,假設hello.c是一個完整的使用bfd庫的程式,則他的編譯方法如下。

gcc hello.c -lbfd -liberty  -ldl -lz

三. 應用執行個體

#include

#include

#include "config.h"

#include

#include

#include

static uint64_t a_haha __attribute__((section ("my_test_sec"))) =3;

static uint64_t b __attribute__((section ("my_test_sec"))) =7;

static uint64_t c __attribute__((section ("my_test_sec"))) =8;

int get_self_path(char *buf, int buf_len)

{

int ret = readlink("/proc/self/exe", buf, buf_len);

buf[ret]='\0';

return ret;

}

void section_proc(bfd *abfd, asection *sect, PTR obj)

{

if (strcmp(sect->name, "my_test_sec")==0)

printf("section %s exists\n", sect->name);

}

void search_a_given_symbol(bfd *ibfd, const char *name)

{

long storage_needed;

asymbol **symbol_table;

long number_of_symbols;

long i;

symbol_info symbolinfo ;

storage_needed = bfd_get_symtab_upper_bound(ibfd);

symbol_table = (void *)(unsigned long)xmalloc(storage_needed);

number_of_symbols = bfd_canonicalize_symtab (ibfd, symbol_table);

printf("Scanning %i symbols\n", number_of_symbols);

for(i=0;i

{

if (symbol_table[i]->section==NULL) continue;

bfd_symbol_info(symbol_table[i],&symbolinfo);

if (strcmp(name, symbolinfo.name)) continue;

printf("Section %s ",symbol_table[i]->section->name);

printf("Symbol \"%s\" value 0x%x\n",

symbolinfo.name, symbolinfo.value);

}

}

int main()

{

char our_self_path[1024];

bfd *ibfd;

char **matching;

asection *psection;

bfd_init();

get_self_path(our_self_path, sizeof(our_self_path));

printf("our elf file path:%s\n", our_self_path);

ibfd = bfd_openr(our_self_path, NULL);

bfd_check_format_matches(ibfd, bfd_object, &matching);

printf("number of sections = %d\n", bfd_count_sections(ibfd));

bfd_map_over_sections(ibfd, section_proc, NULL);

psection = bfd_get_section_by_name(ibfd, "my_test_sec");

printf("section name=%s; start_address=0x%llx; size=%d\n"

, psection->name

, psection->vma

, psection->size);

{

uint64_t *pu64 = (void *) psection->vma;

printf("%lu %lu %lu \n", pu64[0], pu64[1], pu64[2]);

}

printf("address of a_haha=%p\n", &a_haha);

search_a_given_symbol(ibfd, "a_haha");

return 0;

}

最後,程式運作效果如下:

[[email protected] test]# gcc hello.c -lbfd -liberty -ldl -lz

[[email protected] test]# ./a.out

our elf file path:/home/shared/sunmingbao/test/a.out

number of sections = 34

section my_test_sec exists

section name=my_test_sec; start_address=0x6c9a28; size=24

3 7 8

address of a_haha=0x6c9a28

Scanning 1905 symbols

Section my_test_sec Symbol "a_haha" value 0x6c9a28

[[email protected] test]#