2

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

4

0 に答える 0