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

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