00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <private.h>
00025 #include <nlist.h>
00026
00027 #ifndef lint
00028 static const char rcsid[] = "@(#) $Id: nlist.c,v 1.1.1.1 2005/10/21 19:00:00 marcel Exp $";
00029 #endif
00030
00031 #if HAVE_FCNTL_H
00032 #include <fcntl.h>
00033 #endif
00034
00035 #ifndef O_RDONLY
00036 #define O_RDONLY 0
00037 #endif
00038
00039 #ifndef O_BINARY
00040 #define O_BINARY 0
00041 #endif
00042
00043 #define FILE_OPEN_MODE (O_RDONLY | O_BINARY)
00044
00045 #define PRIME 217
00046
00047 struct hash {
00048 const char* name;
00049 unsigned long hash;
00050 unsigned next;
00051 };
00052
00053 static const char*
00054 symbol_name(Elf *elf, const void *syms, const char *names, size_t nlimit, size_t index) {
00055 size_t off;
00056
00057 if (elf->e_class == ELFCLASS32) {
00058 off = ((Elf32_Sym*)syms)[index].st_name;
00059 }
00060 #if __LIBELF64
00061 else if (elf->e_class == ELFCLASS64) {
00062 off = ((Elf64_Sym*)syms)[index].st_name;
00063 }
00064 #endif
00065 else {
00066 return NULL;
00067 }
00068 if (off >= 0 && off < nlimit) {
00069 return &names[off];
00070 }
00071 return NULL;
00072 }
00073
00074 static void
00075 copy_symbol(Elf *elf, struct nlist *np, const void *syms, size_t index) {
00076 if (elf->e_class == ELFCLASS32) {
00077 np->n_value = ((Elf32_Sym*)syms)[index].st_value;
00078 np->n_scnum = ((Elf32_Sym*)syms)[index].st_shndx;
00079 }
00080 #if __LIBELF64
00081 else if (elf->e_class == ELFCLASS64) {
00082 np->n_value = ((Elf64_Sym*)syms)[index].st_value;
00083 np->n_scnum = ((Elf64_Sym*)syms)[index].st_shndx;
00084 }
00085 #endif
00086
00087
00088
00089 np->n_type = 0;
00090 np->n_sclass = 0;
00091 np->n_numaux = 0;
00092 }
00093
00094 static int
00095 _elf_nlist(Elf *elf, struct nlist *nl) {
00096 unsigned first[PRIME];
00097 Elf_Scn *symtab = NULL;
00098 Elf_Scn *strtab = NULL;
00099 Elf_Data *symdata;
00100 Elf_Data *strdata;
00101 size_t symsize;
00102 size_t nsymbols;
00103 const char *name;
00104 struct hash *table;
00105 unsigned long hash;
00106 unsigned i;
00107 struct nlist *np;
00108
00109
00110
00111
00112
00113 if (elf->e_kind != ELF_K_ELF) {
00114 return -1;
00115 }
00116 if (!elf->e_ehdr && !_elf_cook(elf)) {
00117 return -1;
00118 }
00119
00120
00121
00122
00123 for (symtab = elf->e_scn_1; symtab; symtab = symtab->s_link) {
00124 if (symtab->s_type == SHT_SYMTAB) {
00125 break;
00126 }
00127 if (symtab->s_type == SHT_DYNSYM) {
00128 strtab = symtab;
00129 }
00130 }
00131 if (!symtab && !(symtab = strtab)) {
00132 return -1;
00133 }
00134
00135
00136
00137
00138 i = 0;
00139 if (elf->e_class == ELFCLASS32) {
00140 i = symtab->s_shdr32.sh_link;
00141 }
00142 #if __LIBELF64
00143 else if (elf->e_class == ELFCLASS64) {
00144 i = symtab->s_shdr64.sh_link;
00145 }
00146 #endif
00147 if (i == 0) {
00148 return -1;
00149 }
00150 for (strtab = elf->e_scn_1; strtab; strtab = strtab->s_link) {
00151 if (strtab->s_index == i) {
00152 break;
00153 }
00154 }
00155 if (!strtab || strtab->s_type != SHT_STRTAB) {
00156 return -1;
00157 }
00158
00159
00160
00161
00162 symdata = elf_getdata(symtab, NULL);
00163 strdata = elf_getdata(strtab, NULL);
00164 if (!symdata || !strdata) {
00165 return -1;
00166 }
00167 symsize = _msize(elf->e_class, _elf_version, ELF_T_SYM);
00168 elf_assert(symsize);
00169 nsymbols = symdata->d_size / symsize;
00170 if (!symdata->d_buf || !strdata->d_buf || !nsymbols || !strdata->d_size) {
00171 return -1;
00172 }
00173
00174
00175
00176
00177 if (!(table = (struct hash*)malloc(nsymbols * sizeof(*table)))) {
00178 return -1;
00179 }
00180 for (i = 0; i < PRIME; i++) {
00181 first[i] = 0;
00182 }
00183 for (i = 0; i < nsymbols; i++) {
00184 table[i].name = NULL;
00185 table[i].hash = 0;
00186 table[i].next = 0;
00187 }
00188 for (i = 1; i < nsymbols; i++) {
00189 name = symbol_name(elf, symdata->d_buf, strdata->d_buf,
00190 strdata->d_size, i);
00191 if (name == NULL) {
00192 free(table);
00193 return -1;
00194 }
00195 if (*name != '\0') {
00196 table[i].name = name;
00197 table[i].hash = elf_hash((unsigned char *) name);
00198 hash = table[i].hash % PRIME;
00199 table[i].next = first[hash];
00200 first[hash] = i;
00201 }
00202 }
00203
00204
00205
00206
00207 for (np = nl; (name = np->n_name) && *name; np++) {
00208 hash = elf_hash((unsigned char *) name);
00209 for (i = first[hash % PRIME]; i; i = table[i].next) {
00210 if (table[i].hash == hash && !strcmp(table[i].name, name)) {
00211 break;
00212 }
00213 }
00214 if (i) {
00215 copy_symbol(elf, np, symdata->d_buf, i);
00216 }
00217 else {
00218 np->n_value = 0;
00219 np->n_scnum = 0;
00220 np->n_type = 0;
00221 np->n_sclass = 0;
00222 np->n_numaux = 0;
00223 }
00224 }
00225 free(table);
00226 return 0;
00227 }
00228
00229 int
00230 nlist(const char *filename, struct nlist *nl) {
00231 int result = -1;
00232 unsigned oldver;
00233 Elf *elf;
00234 int fd;
00235
00236 if ((oldver = elf_version(EV_CURRENT)) != EV_NONE) {
00237 if ((fd = open(filename, FILE_OPEN_MODE)) != -1) {
00238 if ((elf = elf_begin(fd, ELF_C_READ, NULL))) {
00239 result = _elf_nlist(elf, nl);
00240 elf_end(elf);
00241 }
00242 close(fd);
00243 }
00244 elf_version(oldver);
00245 }
00246 if (result) {
00247 while (nl->n_name && *nl->n_name) {
00248 nl->n_value = 0;
00249 nl++;
00250 }
00251 }
00252 return result;
00253 }