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

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