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

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