Changed the x86 architecture to have tPAddr be 64-bits always
[tpg/acess2.git] / Kernel / bin / elf.c
1 /*\r
2  * Acess v0.1\r
3  * ELF Executable Loader Code\r
4  */\r
5 #define DEBUG   0\r
6 #include <common.h>\r
7 #include <binary.h>\r
8 #include "elf.h"\r
9 \r
10 #define DEBUG_WARN      1\r
11 \r
12 \r
13 // === PROTOTYPES ===\r
14 tBinary *Elf_Load(int fp);\r
15  int    Elf_Relocate(void *Base);\r
16  int    Elf_GetSymbol(void *Base, char *Name, Uint *ret);\r
17  int    Elf_Int_DoRelocate(Uint r_info, Uint32 *ptr, Uint32 addend, Elf32_Sym *symtab, Uint base);\r
18 Uint    Elf_Int_HashString(char *str);\r
19 \r
20 // === GLOBALS ===\r
21 tBinaryType     gELF_Info = {\r
22         NULL,\r
23         0x464C457F, 0xFFFFFFFF, // '\x7FELF'\r
24         "ELF",\r
25         Elf_Load, Elf_Relocate, Elf_GetSymbol\r
26         };\r
27 \r
28 // === CODE ===\r
29 tBinary *Elf_Load(int fp)\r
30 {\r
31         tBinary *ret;\r
32         Elf32_Ehdr      hdr;\r
33         Elf32_Phdr      *phtab;\r
34          int    i, j, k;\r
35          int    iPageCount;\r
36          int    count;\r
37         \r
38         ENTER("ifp", fp);\r
39         \r
40         // Read ELF Header\r
41         VFS_Read(fp, sizeof(hdr), &hdr);\r
42         \r
43         // Check the file type\r
44         if(hdr.ident[0] != 0x7F || hdr.ident[1] != 'E' || hdr.ident[2] != 'L' || hdr.ident[3] != 'F') {\r
45                 Warning("Non-ELF File was passed to the ELF loader\n");\r
46                 LEAVE('n');\r
47                 return NULL;\r
48         }\r
49         \r
50         // Check for a program header\r
51         if(hdr.phoff == 0) {\r
52                 #if DEBUG_WARN\r
53                 Warning("ELF File does not contain a program header\n");\r
54                 #endif\r
55                 LEAVE('n');\r
56                 return NULL;\r
57         }\r
58         \r
59         // Read Program Header Table\r
60         phtab = malloc(sizeof(Elf32_Phdr)*hdr.phentcount);\r
61         VFS_Seek(fp, hdr.phoff, SEEK_SET);\r
62         VFS_Read(fp, sizeof(Elf32_Phdr)*hdr.phentcount, phtab);\r
63         \r
64         // Count Pages\r
65         iPageCount = 0;\r
66         LOG("hdr.phentcount = %i", hdr.phentcount);\r
67         for( i = 0; i < hdr.phentcount; i++ )\r
68         {\r
69                 // Ignore Non-LOAD types\r
70                 if(phtab[i].Type != PT_LOAD)\r
71                         continue;\r
72                 iPageCount += ((phtab[i].VAddr&0xFFF) + phtab[i].MemSize + 0xFFF) >> 12;\r
73                 LOG("phtab[%i] = {VAddr:0x%x, MemSize:0x%x}", i, phtab[i].VAddr, phtab[i].MemSize);\r
74         }\r
75         \r
76         LOG("iPageCount = %i", iPageCount);\r
77         \r
78         // Allocate Information Structure\r
79         ret = malloc( sizeof(tBinary) + sizeof(tBinaryPage)*iPageCount );\r
80         // Fill Info Struct\r
81         ret->Entry = hdr.entrypoint;\r
82         ret->Base = -1;         // Set Base to maximum value\r
83         ret->NumPages = iPageCount;\r
84         ret->Interpreter = NULL;\r
85         \r
86         // Load Pages\r
87         j = 0;\r
88         for( i = 0; i < hdr.phentcount; i++ )\r
89         {\r
90                  int    lastSize;\r
91                 LOG("phtab[%i].Type = 0x%x", i, phtab[i].Type);\r
92                 // Get Interpreter Name\r
93                 if( phtab[i].Type == PT_INTERP )\r
94                 {\r
95                         char *tmp;\r
96                         if(ret->Interpreter)    continue;\r
97                         tmp = malloc(phtab[i].FileSize);\r
98                         VFS_Seek(fp, phtab[i].Offset, 1);\r
99                         VFS_Read(fp, phtab[i].FileSize, tmp);\r
100                         ret->Interpreter = Binary_RegInterp(tmp);\r
101                         LOG("Interpreter '%s'", tmp);\r
102                         free(tmp);\r
103                         continue;\r
104                 }\r
105                 // Ignore non-LOAD types\r
106                 if(phtab[i].Type != PT_LOAD)    continue;\r
107                 \r
108                 // Find Base\r
109                 if(phtab[i].VAddr < ret->Base)  ret->Base = phtab[i].VAddr;\r
110                 \r
111                 LOG("phtab[%i] = {VAddr:0x%x,Offset:0x%x,FileSize:0x%x}",\r
112                         i, phtab[i].VAddr, phtab[i].Offset, phtab[i].FileSize);\r
113                 \r
114                 if( (phtab[i].FileSize & 0xFFF) < 0x1000 - (phtab[i].VAddr & 0xFFF) )\r
115                         lastSize = phtab[i].FileSize;\r
116                 else\r
117                         lastSize = (phtab[i].FileSize & 0xFFF) + (phtab[i].VAddr & 0xFFF);\r
118                 lastSize &= 0xFFF;\r
119                 \r
120                 LOG("lastSize = 0x%x", lastSize);\r
121                 \r
122                 // Get Pages\r
123                 count = ( (phtab[i].VAddr&0xFFF) + phtab[i].FileSize + 0xFFF) >> 12;\r
124                 for( k = 0; k < count; k ++ )\r
125                 {\r
126                         ret->Pages[j+k].Virtual = phtab[i].VAddr + (k<<12);\r
127                         ret->Pages[j+k].Physical = phtab[i].Offset + (k<<12);   // Store the offset in the physical address\r
128                         if(k != 0) {\r
129                                 ret->Pages[j+k].Physical -= ret->Pages[j+k].Virtual&0xFFF;\r
130                                 ret->Pages[j+k].Virtual &= ~0xFFF;\r
131                         }\r
132                         if(k == count-1)\r
133                                 ret->Pages[j+k].Size = lastSize;        // Byte count in page\r
134                         else if(k == 0)\r
135                                 ret->Pages[j+k].Size = 4096 - (phtab[i].VAddr&0xFFF);\r
136                         else\r
137                                 ret->Pages[j+k].Size = 4096;\r
138                         LOG("ret->Pages[%i].Size = 0x%x", j+k, ret->Pages[j+k].Size);\r
139                         ret->Pages[j+k].Flags = 0;\r
140                 }\r
141                 count = (phtab[i].MemSize + 0xFFF) >> 12;\r
142                 for(;k<count;k++)\r
143                 {\r
144                         ret->Pages[j+k].Virtual = phtab[i].VAddr + (k<<12);\r
145                         ret->Pages[j+k].Physical = -1;  // -1 = Fill with zeros\r
146                         if(k != 0)      ret->Pages[j+k].Virtual &= ~0xFFF;\r
147                         if(k == count-1 && (phtab[i].MemSize & 0xFFF))\r
148                                 ret->Pages[j+k].Size = phtab[i].MemSize & 0xFFF;        // Byte count in page\r
149                         else\r
150                                 ret->Pages[j+k].Size = 4096;\r
151                         ret->Pages[j+k].Flags = 0;\r
152                         LOG("%i - 0x%x => 0x%x - 0x%x", j+k,\r
153                                 ret->Pages[j+k].Physical, ret->Pages[j+k].Virtual, ret->Pages[j+k].Size);\r
154                 }\r
155                 j += count;\r
156         }\r
157         \r
158         #if 0\r
159         LOG("Cleaning up overlaps");\r
160         // Clear up Overlaps\r
161         {\r
162                 struct {\r
163                         Uint    V;\r
164                         Uint    P;\r
165                         Uint    S;\r
166                         Uint    F;\r
167                 } *tmpRgns;\r
168                 count = j;\r
169                 tmpRgns = malloc(sizeof(*tmpRgns)*count);\r
170                 // Copy\r
171                 for(i=0;i<count;i++) {\r
172                         tmpRgns[i].V = ret->Pages[i].Virtual;\r
173                         tmpRgns[i].P = ret->Pages[i].Physical;\r
174                         tmpRgns[i].S = ret->Pages[i].Size;\r
175                         tmpRgns[i].F = ret->Pages[i].Flags;\r
176                 }\r
177                 // Compact\r
178                 for(i=1,j=0; i < count; i++)\r
179                 {                       \r
180                         if(     tmpRgns[j].F == tmpRgns[i].F\r
181                         &&      tmpRgns[j].V + tmpRgns[j].S == tmpRgns[i].V\r
182                         &&      ((tmpRgns[j].P == -1 && tmpRgns[i].P == -1)\r
183                         || (tmpRgns[j].P + tmpRgns[j].S == tmpRgns[i].P)) )\r
184                         {\r
185                                 tmpRgns[j].S += tmpRgns[i].S;\r
186                         } else {\r
187                                 j ++;\r
188                                 tmpRgns[j].V = tmpRgns[i].V;\r
189                                 tmpRgns[j].P = tmpRgns[i].P;\r
190                                 tmpRgns[j].F = tmpRgns[i].F;\r
191                                 tmpRgns[j].S = tmpRgns[i].S;\r
192                         }\r
193                 }\r
194                 j ++;\r
195                 // Count\r
196                 count = j;      j = 0;\r
197                 for(i=0;i<count;i++) {\r
198                         //LogF(" Elf_Load: %i - 0x%x => 0x%x - 0x%x\n", i, tmpRgns[i].P, tmpRgns[i].V, tmpRgns[i].S);\r
199                         tmpRgns[i].S += tmpRgns[i].V & 0xFFF;\r
200                         if(tmpRgns[i].P != -1)  tmpRgns[i].P -= tmpRgns[i].V & 0xFFF;\r
201                         tmpRgns[i].V &= ~0xFFF;\r
202                         j += (tmpRgns[i].S + 0xFFF) >> 12;\r
203                         //LogF(" Elf_Load: %i - 0x%x => 0x%x - 0x%x\n", i, tmpRgns[i].P, tmpRgns[i].V, tmpRgns[i].S);\r
204                 }\r
205                 // Reallocate\r
206                 ret = realloc( ret, sizeof(tBinary) + 3*sizeof(Uint)*j );\r
207                 if(!ret) {\r
208                         Warning("BIN", "ElfLoad: Unable to reallocate return structure");\r
209                         return NULL;\r
210                 }\r
211                 ret->NumPages = j;\r
212                 // Split\r
213                 k = 0;\r
214                 for(i=0;i<count;i++) {\r
215                         for( j = 0; j < (tmpRgns[i].S + 0xFFF) >> 12; j++,k++ ) {\r
216                                 ret->Pages[k].Flags = tmpRgns[i].F;\r
217                                 ret->Pages[k].Virtual = tmpRgns[i].V + (j<<12);\r
218                                 if(tmpRgns[i].P != -1) {\r
219                                         ret->Pages[k].Physical = tmpRgns[i].P + (j<<12);\r
220                                 } else\r
221                                         ret->Pages[k].Physical = -1;\r
222                                 ret->Pages[k].Size = tmpRgns[i].S - (j << 12);\r
223                                 // Clamp to page size\r
224                                 if(ret->Pages[k].Size > 0x1000) ret->Pages[k].Size = 0x1000;\r
225                         }\r
226                 }\r
227                 // Free Temp\r
228                 free(tmpRgns);\r
229         }\r
230         #endif\r
231         \r
232         // Clean Up\r
233         free(phtab);\r
234         // Return\r
235         LEAVE('p', ret);\r
236         return ret;\r
237 }\r
238 \r
239 // --- ELF RELOCATION ---\r
240 // Taken from 'ld-acess.so'\r
241 /**\r
242  \fn int Elf_Relocate(void *Base)\r
243  \brief Relocates a loaded ELF Executable\r
244 */\r
245 int Elf_Relocate(void *Base)\r
246 {\r
247         Elf32_Ehdr      *hdr = Base;\r
248         Elf32_Phdr      *phtab;\r
249          int    i, j;   // Counters\r
250         char    *libPath;\r
251         Uint    iRealBase = -1;\r
252         Uint    iBaseDiff;\r
253          int    iSegmentCount;\r
254          int    iSymCount = 0;\r
255         Elf32_Rel       *rel = NULL;\r
256         Elf32_Rela      *rela = NULL;\r
257         Uint32  *pltgot = NULL;\r
258         void    *plt = NULL;\r
259         Uint32  *ptr;\r
260          int    relSz=0, relEntSz=8;\r
261          int    relaSz=0, relaEntSz=8;\r
262          int    pltSz=0, pltType=0;\r
263         Elf32_Dyn       *dynamicTab = NULL;     // Dynamic Table Pointer\r
264         char    *dynstrtab = NULL;      // .dynamic String Table\r
265         Elf32_Sym       *dynsymtab = NULL;\r
266          int    bFailed = 0;\r
267         \r
268         ENTER("pBase", Base);\r
269         \r
270         // Parse Program Header to get Dynamic Table\r
271         phtab = Base + hdr->phoff;\r
272         iSegmentCount = hdr->phentcount;\r
273         for(i=0;i<iSegmentCount;i++)\r
274         {\r
275                 // Determine linked base address\r
276                 if(phtab[i].Type == PT_LOAD && iRealBase > phtab[i].VAddr)\r
277                         iRealBase = phtab[i].VAddr;\r
278                 \r
279                 // Find Dynamic Section\r
280                 if(phtab[i].Type == PT_DYNAMIC) {\r
281                         if(dynamicTab) {\r
282                                 Warning("ELF", "Elf_Relocate - Multiple PT_DYNAMIC segments\n");\r
283                                 continue;\r
284                         }\r
285                         dynamicTab = (void *) phtab[i].VAddr;\r
286                         j = i;  // Save Dynamic Table ID\r
287                         break;\r
288                 }\r
289         }\r
290         \r
291         // Check if a PT_DYNAMIC segement was found\r
292         if(!dynamicTab) {\r
293                 Warning("ELF", "Elf_Relocate: No PT_DYNAMIC segment in image, returning\n");\r
294                 LEAVE('x', hdr->entrypoint);\r
295                 return hdr->entrypoint;\r
296         }\r
297         \r
298         // Page Align real base\r
299         iRealBase &= ~0xFFF;\r
300         \r
301         // Adjust "Real" Base\r
302         iBaseDiff = (Uint)Base - iRealBase;\r
303         // Adjust Dynamic Table\r
304         dynamicTab = (void *) ((Uint)dynamicTab + iBaseDiff);\r
305         \r
306         // === Get Symbol table and String Table ===\r
307         for( j = 0; dynamicTab[j].d_tag != DT_NULL; j++)\r
308         {\r
309                 switch(dynamicTab[j].d_tag)\r
310                 {\r
311                 // --- Symbol Table ---\r
312                 case DT_SYMTAB:\r
313                         dynamicTab[j].d_val += iBaseDiff;\r
314                         dynsymtab = (void*)(dynamicTab[j].d_val);\r
315                         hdr->misc.SymTable = dynamicTab[j].d_val;       // Saved in unused bytes of ident\r
316                         break;\r
317                 \r
318                 // --- String Table ---\r
319                 case DT_STRTAB:\r
320                         dynamicTab[j].d_val += iBaseDiff;\r
321                         dynstrtab = (void*)(dynamicTab[j].d_val);\r
322                         break;\r
323                 \r
324                 // --- Hash Table --\r
325                 case DT_HASH:\r
326                         dynamicTab[j].d_val += iBaseDiff;\r
327                         iSymCount = ((Uint*)(dynamicTab[j].d_val))[1];\r
328                         hdr->misc.HashTable = dynamicTab[j].d_val;      // Saved in unused bytes of ident\r
329                         break;\r
330                 }\r
331         }\r
332 \r
333 \r
334         // Alter Symbols to true base\r
335         for(i=0;i<iSymCount;i++)\r
336         {\r
337                 dynsymtab[i].value += iBaseDiff;\r
338                 dynsymtab[i].nameOfs += (Uint)dynstrtab;\r
339                 //LOG("Sym '%s' = 0x%x (relocated)\n", dynsymtab[i].name, dynsymtab[i].value);\r
340         }\r
341         \r
342         // === Add to loaded list (can be imported now) ===\r
343         //Binary_AddLoaded( (Uint)Base );\r
344 \r
345         // === Parse Relocation Data ===\r
346         for( j = 0; dynamicTab[j].d_tag != DT_NULL; j++)\r
347         {\r
348                 switch(dynamicTab[j].d_tag)\r
349                 {\r
350                 // --- Shared Library Name ---\r
351                 case DT_SONAME:\r
352                         LOG(".so Name '%s'\n", dynstrtab+dynamicTab[j].d_val);\r
353                         break;\r
354                 // --- Needed Library ---\r
355                 case DT_NEEDED:\r
356                         libPath = dynstrtab + dynamicTab[j].d_val;\r
357                         LOG("Required Library '%s' (IGNORED in kernel mode)\n", libPath);\r
358                         break;\r
359                 // --- PLT/GOT ---\r
360                 case DT_PLTGOT: pltgot = (void*)iBaseDiff+(dynamicTab[j].d_val);        break;\r
361                 case DT_JMPREL: plt = (void*)(iBaseDiff+dynamicTab[j].d_val);   break;\r
362                 case DT_PLTREL: pltType = dynamicTab[j].d_val;  break;\r
363                 case DT_PLTRELSZ:       pltSz = dynamicTab[j].d_val;    break;\r
364                 \r
365                 // --- Relocation ---\r
366                 case DT_REL:    rel = (void*)(iBaseDiff + dynamicTab[j].d_val); break;\r
367                 case DT_RELSZ:  relSz = dynamicTab[j].d_val;    break;\r
368                 case DT_RELENT: relEntSz = dynamicTab[j].d_val; break;\r
369                 case DT_RELA:   rela = (void*)(iBaseDiff + dynamicTab[j].d_val);        break;\r
370                 case DT_RELASZ: relaSz = dynamicTab[j].d_val;   break;\r
371                 case DT_RELAENT:        relaEntSz = dynamicTab[j].d_val;        break;\r
372                 }\r
373         }\r
374         \r
375         // Parse Relocation Entries\r
376         if(rel && relSz)\r
377         {\r
378                 j = relSz / relEntSz;\r
379                 for( i = 0; i < j; i++ )\r
380                 {\r
381                         ptr = (void*)(iBaseDiff + rel[i].r_offset);\r
382                         if( !Elf_Int_DoRelocate(rel[i].r_info, ptr, *ptr, dynsymtab, (Uint)Base) ) {\r
383                                 bFailed = 1;\r
384                         }\r
385                 }\r
386         }\r
387         // Parse Relocation Entries\r
388         if(rela && relaSz)\r
389         {\r
390                 j = relaSz / relaEntSz;\r
391                 for( i = 0; i < j; i++ )\r
392                 {\r
393                         ptr = (void*)(iBaseDiff + rela[i].r_offset);\r
394                         if( !Elf_Int_DoRelocate(rel[i].r_info, ptr, rela[i].r_addend, dynsymtab, (Uint)Base) ) {\r
395                                 bFailed = 1;\r
396                         }\r
397                 }\r
398         }\r
399         \r
400         // === Process PLT (Procedure Linkage Table) ===\r
401         if(plt && pltSz)\r
402         {\r
403                 if(pltType == DT_REL)\r
404                 {\r
405                         Elf32_Rel       *pltRel = plt;\r
406                         j = pltSz / sizeof(Elf32_Rel);\r
407                         for(i = 0; i < j; i++)\r
408                         {\r
409                                 ptr = (void*)(iBaseDiff + pltRel[i].r_offset);\r
410                                 if( !Elf_Int_DoRelocate(pltRel[i].r_info, ptr, *ptr, dynsymtab, (Uint)Base) ) {\r
411                                         bFailed = 1;\r
412                                 }\r
413                         }\r
414                 }\r
415                 else\r
416                 {\r
417                         Elf32_Rela      *pltRela = plt;\r
418                         j = pltSz / sizeof(Elf32_Rela);\r
419                         for(i=0;i<j;i++)\r
420                         {\r
421                                 ptr = (void*)((Uint)Base + pltRela[i].r_offset);\r
422                                 if( !Elf_Int_DoRelocate(pltRela[i].r_info, ptr, pltRela[i].r_addend, dynsymtab, (Uint)Base) ) {\r
423                                         bFailed = 1;\r
424                                 }\r
425                         }\r
426                 }\r
427         }\r
428         \r
429         if(bFailed) {\r
430                 LEAVE('i', 0);\r
431                 return 0;\r
432         }\r
433         \r
434         LEAVE('x', hdr->entrypoint);\r
435         return hdr->entrypoint;\r
436 }\r
437 \r
438 /**\r
439  * \fn void Elf_Int_DoRelocate(Uint r_info, Uint32 *ptr, Uint32 addend, Elf32_Sym *symtab, Uint base)\r
440  * \brief Performs a relocation\r
441  * \param r_info        Field from relocation entry\r
442  * \param ptr   Pointer to location of relocation\r
443  * \param addend        Value to add to symbol\r
444  * \param symtab        Symbol Table\r
445  * \param base  Base of loaded binary\r
446  */\r
447 int Elf_Int_DoRelocate(Uint r_info, Uint32 *ptr, Uint32 addend, Elf32_Sym *symtab, Uint base)\r
448 {\r
449         Uint    val;\r
450          int    type = ELF32_R_TYPE(r_info);\r
451          int    sym = ELF32_R_SYM(r_info);\r
452         char    *sSymName = symtab[sym].name;\r
453         \r
454         //LogF("Elf_Int_DoRelocate: (r_info=0x%x, ptr=0x%x, addend=0x%x, .., base=0x%x)\n",\r
455         //      r_info, ptr, addend, base);\r
456         \r
457         switch( type )\r
458         {\r
459         // Standard 32 Bit Relocation (S+A)\r
460         case R_386_32:\r
461                 if( !Elf_GetSymbol((void*)base, sSymName, &val) )       // Search this binary first\r
462                         if( !Binary_GetSymbol( sSymName, &val ) )\r
463                                 return 0;\r
464                 //LOG("R_386_32 *0x%x += 0x%x('%s')", ptr, val, sSymName);\r
465                 *ptr = val + addend;\r
466                 break;\r
467                 \r
468         // 32 Bit Relocation wrt. Offset (S+A-P)\r
469         case R_386_PC32:\r
470                 if( !Elf_GetSymbol( (void*)base, sSymName, &val ) )\r
471                         if( !Binary_GetSymbol( sSymName, &val ) )\r
472                                 return 0;\r
473                 //LOG("R_386_PC32 *0x%x = 0x%x + 0x%x('%s') - 0x%x", ptr, *ptr, val, sSymName, (Uint)ptr );\r
474                 // TODO: Check if it needs the true value of ptr or the compiled value\r
475                 // NOTE: Testing using true value\r
476                 *ptr = val + addend - (Uint)ptr;\r
477                 break;\r
478 \r
479         // Absolute Value of a symbol (S)\r
480         case R_386_GLOB_DAT:\r
481                 if( !Elf_GetSymbol( (void*)base, sSymName, &val ) )\r
482                         if( !Binary_GetSymbol( sSymName, &val ) )\r
483                                 return 0;\r
484                 //LOG("R_386_GLOB_DAT *0x%x = 0x%x (%s)", ptr, val, sSymName);\r
485                 *ptr = val;\r
486                 break;\r
487         \r
488         // Absolute Value of a symbol (S)\r
489         case R_386_JMP_SLOT:\r
490                 if( !Elf_GetSymbol( (void*)base, sSymName, &val ) )\r
491                         if( !Binary_GetSymbol( sSymName, &val ) )\r
492                                 return 0;\r
493                 //LOG("R_386_JMP_SLOT *0x%x = 0x%x (%s)", ptr, val, sSymName);\r
494                 *ptr = val;\r
495                 break;\r
496 \r
497         // Base Address (B+A)\r
498         case R_386_RELATIVE:\r
499                 //LOG("R_386_RELATIVE *0x%x = 0x%x + 0x%x", ptr, base, addend);\r
500                 *ptr = base + addend;\r
501                 break;\r
502                 \r
503         default:\r
504                 LOG("Rel 0x%x: 0x%x,%i", ptr, sym, type);\r
505                 break;\r
506         }\r
507         return 1;\r
508 }\r
509 \r
510 /**\r
511  * \fn int Elf_GetSymbol(void *Base, char *name, Uint *ret)\r
512  * \brief Get a symbol from the loaded binary\r
513  */\r
514 int Elf_GetSymbol(void *Base, char *Name, Uint *ret)\r
515 {\r
516         Elf32_Ehdr      *hdr = (void*)Base;\r
517         Elf32_Sym       *symtab;\r
518          int    nbuckets = 0;\r
519          int    iSymCount = 0;\r
520          int    i;\r
521         Uint    *pBuckets;\r
522         Uint    *pChains;\r
523         Uint    iNameHash;\r
524 \r
525         if(!Base)       return 0;\r
526 \r
527         pBuckets = (void *) hdr->misc.HashTable;\r
528         symtab = (void *) hdr->misc.SymTable;\r
529         \r
530         nbuckets = pBuckets[0];\r
531         iSymCount = pBuckets[1];\r
532         pBuckets = &pBuckets[2];\r
533         pChains = &pBuckets[ nbuckets ];\r
534         \r
535         // Get hash\r
536         iNameHash = Elf_Int_HashString(Name);\r
537         iNameHash %= nbuckets;\r
538 \r
539         // Check Bucket\r
540         i = pBuckets[ iNameHash ];\r
541         if(symtab[i].shndx != SHN_UNDEF && strcmp(symtab[i].name, Name) == 0) {\r
542                 *ret = symtab[ i ].value;\r
543                 return 1;\r
544         }\r
545         \r
546         // Walk Chain\r
547         while(pChains[i] != STN_UNDEF)\r
548         {\r
549                 i = pChains[i];\r
550                 if(symtab[i].shndx != SHN_UNDEF && strcmp(symtab[ i ].name, Name) == 0) {\r
551                         *ret = symtab[ i ].value;\r
552                         return 1;\r
553                 }\r
554         }\r
555         return 0;\r
556 }\r
557 \r
558 /**\r
559  * \fn Uint Elf_Int_HashString(char *str)\r
560  * \brief Hash a string in the ELF format\r
561  * \param str   String to hash\r
562  * \return Hash value\r
563  */\r
564 Uint Elf_Int_HashString(char *str)\r
565 {\r
566         Uint    h = 0, g;\r
567         while(*str)\r
568         {\r
569                 h = (h << 4) + *str++;\r
570                 if( (g = h & 0xf0000000) )\r
571                         h ^= g >> 24;\r
572                 h &= ~g;\r
573         }\r
574         return h;\r
575 }\r

UCC git Repository :: git.ucc.asn.au