summaryrefslogtreecommitdiff
path: root/ldso/ldso/dl-hash.c
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2001-05-01 14:20:45 +0000
committerEric Andersen <andersen@codepoet.org>2001-05-01 14:20:45 +0000
commitb7bc129184a23d4c9c70774362f4eeaa5e0b44c8 (patch)
treef42053a86d7e4f8c156663b4c9c791deef7e2ef5 /ldso/ldso/dl-hash.c
parent22a9e5bbdf43e1086d80341480d0601ee9c6f898 (diff)
Yet another major rework. This time around, rework it to no longer
use linux kernel header files. -Erik
Diffstat (limited to 'ldso/ldso/dl-hash.c')
-rw-r--r--ldso/ldso/dl-hash.c400
1 files changed, 201 insertions, 199 deletions
diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c
index 048c27738..fa610e012 100644
--- a/ldso/ldso/dl-hash.c
+++ b/ldso/ldso/dl-hash.c
@@ -20,11 +20,7 @@
/* Various symbol table handling functions, including symbol lookup */
-/*#include <stdlib.h>*/
#include "string.h"
-#include <linux/unistd.h>
-#include <linux/elf.h>
-
#include "dlfcn.h"
#include "hash.h"
#include "linuxelf.h"
@@ -38,20 +34,20 @@
* as well as all of the other good stuff in the binary.
*/
-struct elf_resolve * _dl_loaded_modules = NULL;
+struct elf_resolve *_dl_loaded_modules = NULL;
/*
* This is the list of modules that are loaded when the image is first
* started. As we add more via dlopen, they get added into other
* chains.
*/
-struct dyn_elf * _dl_symbol_tables = NULL;
+struct dyn_elf *_dl_symbol_tables = NULL;
/*
* This is the list of modules that are loaded via dlopen. We may need
* to search these for RTLD_GLOBAL files.
*/
-struct dyn_elf * _dl_handles = NULL;
+struct dyn_elf *_dl_handles = NULL;
/*
@@ -60,32 +56,35 @@ struct dyn_elf * _dl_handles = NULL;
* have. We need it to decode the hash table.
*/
-unsigned long _dl_elf_hash(const char * name){
- unsigned long hash = 0;
- unsigned long tmp;
+unsigned long _dl_elf_hash(const char *name)
+{
+ unsigned long hash = 0;
+ unsigned long tmp;
- while (*name){
- hash = (hash << 4) + *name++;
- if((tmp = hash & 0xf0000000)) hash ^= tmp >> 24;
- hash &= ~tmp;
- };
- return hash;
+ while (*name) {
+ hash = (hash << 4) + *name++;
+ if ((tmp = hash & 0xf0000000))
+ hash ^= tmp >> 24;
+ hash &= ~tmp;
+ };
+ return hash;
}
/*
* Check to see if a library has already been added to the hash chain.
*/
-struct elf_resolve * _dl_check_hashed_files(char * libname){
- struct elf_resolve * tpnt;
- int len = _dl_strlen(libname);
+struct elf_resolve *_dl_check_hashed_files(char *libname)
+{
+ struct elf_resolve *tpnt;
+ int len = _dl_strlen(libname);
- for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
- if (_dl_strncmp(tpnt->libname, libname, len) == 0 &&
- (tpnt->libname[len] == '\0' || tpnt->libname[len] == '.'))
- return tpnt;
- }
+ for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
+ if (_dl_strncmp(tpnt->libname, libname, len) == 0 &&
+ (tpnt->libname[len] == '\0' || tpnt->libname[len] == '.'))
+ return tpnt;
+ }
- return NULL;
+ return NULL;
}
/*
@@ -94,48 +93,47 @@ struct elf_resolve * _dl_check_hashed_files(char * libname){
* externals properly.
*/
-struct elf_resolve * _dl_add_elf_hash_table(char * libname,
- char * loadaddr,
- unsigned int * dynamic_info,
- unsigned int dynamic_addr,
- unsigned int dynamic_size){
- unsigned int * hash_addr;
- struct elf_resolve * tpnt;
- int i;
-
- if (!_dl_loaded_modules) {
- tpnt = _dl_loaded_modules =
- (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve));
- _dl_memset (tpnt, 0, sizeof (*tpnt));
- }
- else {
- tpnt = _dl_loaded_modules;
- while(tpnt->next) tpnt = tpnt->next;
- tpnt->next = (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve));
- _dl_memset (tpnt->next, 0, sizeof (*(tpnt->next)));
- tpnt->next->prev = tpnt;
- tpnt = tpnt->next;
- };
-
- tpnt->next = NULL;
- tpnt->init_flag = 0;
- tpnt->libname = _dl_strdup(libname);
- tpnt->dynamic_addr = dynamic_addr;
- tpnt->dynamic_size = dynamic_size;
- tpnt->libtype = loaded_file;
-
- if( dynamic_info[DT_HASH] != 0 )
- {
- hash_addr = (unsigned int *) (dynamic_info[DT_HASH] + loadaddr);
- tpnt->nbucket = *hash_addr++;
- tpnt->nchain = *hash_addr++;
- tpnt->elf_buckets = hash_addr;
- hash_addr += tpnt->nbucket;
- tpnt->chains = hash_addr;
- }
- tpnt->loadaddr = loadaddr;
- for(i=0; i<24; i++) tpnt->dynamic_info[i] = dynamic_info[i];
- return tpnt;
+struct elf_resolve *_dl_add_elf_hash_table(char *libname,
+ char *loadaddr, unsigned int *dynamic_info, unsigned int dynamic_addr,
+ unsigned int dynamic_size)
+{
+ unsigned int *hash_addr;
+ struct elf_resolve *tpnt;
+ int i;
+
+ if (!_dl_loaded_modules) {
+ tpnt = _dl_loaded_modules =
+ (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve));
+ _dl_memset(tpnt, 0, sizeof(*tpnt));
+ } else {
+ tpnt = _dl_loaded_modules;
+ while (tpnt->next)
+ tpnt = tpnt->next;
+ tpnt->next = (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve));
+ _dl_memset(tpnt->next, 0, sizeof(*(tpnt->next)));
+ tpnt->next->prev = tpnt;
+ tpnt = tpnt->next;
+ };
+
+ tpnt->next = NULL;
+ tpnt->init_flag = 0;
+ tpnt->libname = _dl_strdup(libname);
+ tpnt->dynamic_addr = dynamic_addr;
+ tpnt->dynamic_size = dynamic_size;
+ tpnt->libtype = loaded_file;
+
+ if (dynamic_info[DT_HASH] != 0) {
+ hash_addr = (unsigned int *) (dynamic_info[DT_HASH] + loadaddr);
+ tpnt->nbucket = *hash_addr++;
+ tpnt->nchain = *hash_addr++;
+ tpnt->elf_buckets = hash_addr;
+ hash_addr += tpnt->nbucket;
+ tpnt->chains = hash_addr;
+ }
+ tpnt->loadaddr = loadaddr;
+ for (i = 0; i < 24; i++)
+ tpnt->dynamic_info[i] = dynamic_info[i];
+ return tpnt;
}
@@ -144,141 +142,145 @@ struct elf_resolve * _dl_add_elf_hash_table(char * libname,
* relocations or when we call an entry in the PLT table for the first time.
*/
-char * _dl_find_hash(char * name, struct dyn_elf * rpnt1,
- unsigned int instr_addr, struct elf_resolve * f_tpnt,
- int copyrel){
- struct elf_resolve * tpnt;
- int si;
- char * pnt;
- int pass;
- char * strtab;
- struct elf32_sym * symtab;
- unsigned int elf_hash_number, hn;
- char * weak_result;
- struct elf_resolve * first_def;
- struct dyn_elf * rpnt, first;
- char * data_result = 0; /* nakao */
-
- weak_result = 0;
- elf_hash_number = _dl_elf_hash(name);
-
- /* A quick little hack to make sure that any symbol in the executable
- will be preferred to one in a shared library. This is necessary so
- that any shared library data symbols referenced in the executable
- will be seen at the same address by the executable, shared libraries
- and dynamically loaded code. -Rob Ryan (robr@cmu.edu) */
- if(!copyrel && rpnt1) {
- first=(*_dl_symbol_tables);
- first.next=rpnt1;
- rpnt1=(&first);
- }
-
- /*
- * The passes are so that we can first search the regular symbols
- * for whatever module was specified, and then search anything
- * loaded with RTLD_GLOBAL. When pass is 1, it means we are just
- * starting the first dlopened module, and anything above that
- * is just the next one in the chain.
- */
- for(pass = 0; (1==1); pass++)
- {
-
- /*
- * If we are just starting to search for RTLD_GLOBAL, setup
- * the pointer for the start of the search.
- */
- if( pass == 1) {
- rpnt1 = _dl_handles;
- }
-
- /*
- * Anything after this, we need to skip to the next module.
- */
- else if( pass >= 2) {
- rpnt1 = rpnt1->next_handle;
- }
-
- /*
- * Make sure we still have a module, and make sure that this
- * module was loaded with RTLD_GLOBAL.
- */
- if( pass != 0 )
- {
- if( rpnt1 == NULL ) break;
- if( (rpnt1->flags & RTLD_GLOBAL) == 0) continue;
+char *_dl_find_hash(char *name, struct dyn_elf *rpnt1,
+ unsigned int instr_addr, struct elf_resolve *f_tpnt, int copyrel)
+{
+ struct elf_resolve *tpnt;
+ int si;
+ char *pnt;
+ int pass;
+ char *strtab;
+ Elf32_Sym *symtab;
+ unsigned int elf_hash_number, hn;
+ char *weak_result;
+ struct elf_resolve *first_def;
+ struct dyn_elf *rpnt, first;
+ char *data_result = 0; /* nakao */
+
+ weak_result = 0;
+ elf_hash_number = _dl_elf_hash(name);
+
+ /* A quick little hack to make sure that any symbol in the executable
+ will be preferred to one in a shared library. This is necessary so
+ that any shared library data symbols referenced in the executable
+ will be seen at the same address by the executable, shared libraries
+ and dynamically loaded code. -Rob Ryan (robr@cmu.edu) */
+ if (!copyrel && rpnt1) {
+ first = (*_dl_symbol_tables);
+ first.next = rpnt1;
+ rpnt1 = (&first);
}
- for(rpnt = (rpnt1 ? rpnt1 : _dl_symbol_tables);
- rpnt; rpnt = rpnt->next) {
- tpnt = rpnt->dyn;
-
- /*
- * The idea here is that if we are using dlsym, we want to
- * first search the entire chain loaded from dlopen, and
- * return a result from that if we found anything. If this
- * fails, then we continue the search into the stuff loaded
- * when the image was activated. For normal lookups, we start
- * with rpnt == NULL, so we should never hit this.
- */
- if( tpnt->libtype == elf_executable
- && weak_result != 0 )
- {
- break;
- }
-
- /*
- * Avoid calling .urem here.
- */
- do_rem(hn, elf_hash_number, tpnt->nbucket);
- symtab = (struct elf32_sym *) (tpnt->dynamic_info[DT_SYMTAB] +
- tpnt->loadaddr);
- strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
/*
- * This crap is required because the first instance of a
- * symbol on the chain will be used for all symbol references.
- * Thus this instance must be resolved to an address that
- * contains the actual function,
+ * The passes are so that we can first search the regular symbols
+ * for whatever module was specified, and then search anything
+ * loaded with RTLD_GLOBAL. When pass is 1, it means we are just
+ * starting the first dlopened module, and anything above that
+ * is just the next one in the chain.
*/
-
- first_def = NULL;
-
- for(si = tpnt->elf_buckets[hn]; si; si = tpnt->chains[si]){
- pnt = strtab + symtab[si].st_name;
-
- if(_dl_strcmp(pnt, name) == 0 &&
- (ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC ||
- ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE ||
- ELF32_ST_TYPE(symtab[si].st_info) == STT_OBJECT) &&
- symtab[si].st_value != 0) {
-
- /* Here we make sure that we find a module where the symbol is
- * actually defined.
- */
-
- if(f_tpnt) {
- if(!first_def) first_def = tpnt;
- if(first_def == f_tpnt && symtab[si].st_shndx == 0)
- continue;
- }
-
- switch(ELF32_ST_BIND(symtab[si].st_info)){
- case STB_GLOBAL:
- if ( tpnt->libtype != elf_executable
- && ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE) { /* nakao */
- data_result = tpnt->loadaddr + symtab[si].st_value; /* nakao */
- break; /* nakao */
- } else /* nakao */
- return tpnt->loadaddr + symtab[si].st_value;
- case STB_WEAK:
- if (!weak_result) weak_result = tpnt->loadaddr + symtab[si].st_value;
- break;
- default: /* Do local symbols need to be examined? */
- break;
- }
- }
+ for (pass = 0; (1 == 1); pass++) {
+
+ /*
+ * If we are just starting to search for RTLD_GLOBAL, setup
+ * the pointer for the start of the search.
+ */
+ if (pass == 1) {
+ rpnt1 = _dl_handles;
+ }
+
+ /*
+ * Anything after this, we need to skip to the next module.
+ */
+ else if (pass >= 2) {
+ rpnt1 = rpnt1->next_handle;
+ }
+
+ /*
+ * Make sure we still have a module, and make sure that this
+ * module was loaded with RTLD_GLOBAL.
+ */
+ if (pass != 0) {
+ if (rpnt1 == NULL)
+ break;
+ if ((rpnt1->flags & RTLD_GLOBAL) == 0)
+ continue;
+ }
+
+ for (rpnt = (rpnt1 ? rpnt1 : _dl_symbol_tables); rpnt; rpnt = rpnt->next) {
+ tpnt = rpnt->dyn;
+
+ /*
+ * The idea here is that if we are using dlsym, we want to
+ * first search the entire chain loaded from dlopen, and
+ * return a result from that if we found anything. If this
+ * fails, then we continue the search into the stuff loaded
+ * when the image was activated. For normal lookups, we start
+ * with rpnt == NULL, so we should never hit this.
+ */
+ if (tpnt->libtype == elf_executable && weak_result != 0) {
+ break;
+ }
+
+ /*
+ * Avoid calling .urem here.
+ */
+ do_rem(hn, elf_hash_number, tpnt->nbucket);
+ symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
+ strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+ /*
+ * This crap is required because the first instance of a
+ * symbol on the chain will be used for all symbol references.
+ * Thus this instance must be resolved to an address that
+ * contains the actual function,
+ */
+
+ first_def = NULL;
+
+ for (si = tpnt->elf_buckets[hn]; si; si = tpnt->chains[si]) {
+ pnt = strtab + symtab[si].st_name;
+
+ if (_dl_strcmp(pnt, name) == 0 &&
+ (ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC ||
+ ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE ||
+ ELF32_ST_TYPE(symtab[si].st_info) == STT_OBJECT) &&
+ symtab[si].st_value != 0) {
+
+ /* Here we make sure that we find a module where the symbol is
+ * actually defined.
+ */
+
+ if (f_tpnt) {
+ if (!first_def)
+ first_def = tpnt;
+ if (first_def == f_tpnt
+ && symtab[si].st_shndx == 0)
+ continue;
+ }
+
+ switch (ELF32_ST_BIND(symtab[si].st_info)) {
+ case STB_GLOBAL:
+ if (tpnt->libtype != elf_executable &&
+ ELF32_ST_TYPE(symtab[si].st_info)
+ == STT_NOTYPE)
+ { /* nakao */
+ data_result = tpnt->loadaddr +
+ symtab[si].st_value; /* nakao */
+ break; /* nakao */
+ } else /* nakao */
+ return tpnt->loadaddr + symtab[si].st_value;
+ case STB_WEAK:
+ if (!weak_result)
+ weak_result =
+ tpnt->loadaddr + symtab[si].st_value;
+ break;
+ default: /* Do local symbols need to be examined? */
+ break;
+ }
+ }
+ }
+ }
}
- }
- }
- if (data_result) return data_result; /* nakao */
- return weak_result;
+ if (data_result)
+ return data_result; /* nakao */
+ return weak_result;
}