ELF ファイル内のシンボルを検索するコードを書いています。私のコードでは、ELF ファイルを開き、すべてのセグメントをメモリにマップし、さまざまなセクションとテーブルに関連するすべての情報をこのような構造に格納します。
typedef struct Struct_Obj_Entry{
//Name of the file
const char *filepath;
//File pointer
void* ELF_fp;
//Metadata of ELF header and Progam header tables
Elf32_Ehdr* Ehdr;
Elf32_Phdr* Phdr_array;
//base address of mapped region
uint32 mapbase;
//DYNAMIC Segment
uint32 *dynamic;
//DT_SYMTAB
Elf32_Sym *symtab; //Ptr to DT_SYMTAB
//DT_STRTAB
char *strtab;
//DT_HASH
uint32 *hashtab;//Ptr to DT_HASH
//Hash table variables
int nbuckets, nchains;
uint32 *buckets,
*chains;
} Obj_Entry;
この部分は完全に正常に機能し、すべての構造要素が正しく設定され、マップされた ELF ファイルの領域への有効なアドレスが保持されます。
シンボル名を検索する方法は次のとおりです。
void *return_symbol_vaddr(Obj_Entry *obj, const char *name){
unsigned long hash_value;
uint32 y=0,z=0;
/*following part is DLSYM code to locate a symbol in a given file*/
//Lets query for a symbol name
hash_value = elf_Hash(name);
printf("hash value =%lu\n",hash_value);
//See if correct symbol entry found in bucket list
//If it is break out
y = (obj->buckets[hash_value % obj->nbuckets]);
if((!strcmp(name, obj->strtab + obj->symtab[z].st_name))) {
return (void*)(obj->mapbase + (obj->symtab[z]).st_value);
}
//If not there is a collision
else{
while(obj->chains[y] !=0){
z = obj->chains[y];
if((!strcmp(name, obj->strtab + obj->symtab[z].st_name))) {
//return (void*)(obj->symtab[z].st_value);
return (void*)(obj->mapbase + obj->symtab[z].st_value);
}
else{
//If the symbol is not found in chains
//There is double collision
//In that case chain[y] gives the next symbol table entry with the same hash value
y = z;
}
}
}
}
文字列ハッシュ関数は、標準の ABI 仕様です。
//Get hash value for a symbol name
unsigned long
elf_Hash(const unsigned char *name)
{
unsigned long h = 0, g;
while (*name)
{
h = (h << 4) + *name++;
if (g = h & 0xf0000000)
h ^= g >> 24;
h &= ~g;
}
return h;
}
問題は、位置に依存しないsoファイルをコンパイルしてシンボルを探しようとするときです。シンボルの一部を見つけることができ、残りのシンボルについては関数が NULL 値を返します。
サンプル ELF ファイル
typedef struct _data{
int x;
int y;
}data;
int add(void){
return 1;
}
int sub(void){
return 4;
}
data Data ={3, 2};
このファイルを ELF にコンパイルすると、追加のデータ シンボルが見つかりますが、驚くべきことに「サブ」が見つかりません。.so ファイルで readelf を実行すると、sub が動的シンボルの DT_SYMTAB リストに表示されることがわかります。
コードのバグを特定できる人はいますか? これは、シンボルがどのようにパックされるかへのリンクです http://docs.oracle.com/cd/E19082-01/819-0690/chapter6-48031/index.html