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

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