|
1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // ELFDLLD.CPP |
|
15 // |
|
16 // |
|
17 |
|
18 |
|
19 #include <string.h> |
|
20 #include <stdlib.h> |
|
21 #include <e32std.h> |
|
22 #include <e32std_private.h> |
|
23 #include <tools/elfdefs.h> |
|
24 #include "elfdll.h" |
|
25 #include "elffile.h" |
|
26 #include "h_utl.h" |
|
27 #include <e32ldr.h> |
|
28 |
|
29 ELFFile::ELFDllData::ELFDllData(ELFFile * f) : |
|
30 iElfFile(f), iDynStrTab(0), iDynStrTabSize(0), iDynSymTab(0), |
|
31 iSymSize(0), iRela(0), iRelaSz(0), iRelaEnt(0), |
|
32 iRel(0), iRelSz(0), iRelEnt(0), |
|
33 iHashTable(0),iDllHead(0), iDllTail(0), |
|
34 iNumberOfImports(0), iNumberOfExports(0), iNumberOfImportDlls(0), |
|
35 iStringTableSize(0), iNumberOfRelocs(0), iNumberOfCodeRelocs(0), |
|
36 iNumberOfDataRelocs(0), iNamedLookupEnabled(0), iNamedExportSymbolHead(0), |
|
37 iNamedExportCount(0), iSymStringTableSize(0),iStringNameOffset(0), iOrdZeroRec(0), |
|
38 iDepRecords(0), iDepRecordsTail(0),iNeededDllNames(0), |
|
39 iNeededDllNamesTail(0) |
|
40 { |
|
41 } |
|
42 |
|
43 ELFFile::ELFDllData::~ELFDllData() |
|
44 { |
|
45 delete iOrdZeroRec; |
|
46 delete iDepRecords; |
|
47 delete iNeededDllNames; |
|
48 } |
|
49 |
|
50 TBool ELFFile::ELFDllData::Init() |
|
51 { |
|
52 // process imported symbols |
|
53 // There will be at least one relocation (assumed to be Elf32_Rel) for each such symbol. |
|
54 // S iterate over relocations looking for DLL symbols and add them to the record of |
|
55 // of import info. |
|
56 TInt nrelocs = iRelSz/iRelEnt; |
|
57 TInt SrcSegIdx = -1; |
|
58 TInt errors = 0; |
|
59 |
|
60 for (TInt idx = 0; idx < nrelocs; idx++) |
|
61 { |
|
62 Elf32_Rel * rel = &iRel[idx]; |
|
63 TUint relType = ELF32_R_TYPE(rel->r_info); |
|
64 |
|
65 if (relType == R_ARM_ABS32) |
|
66 { |
|
67 TInt symIdx = ELF32_R_SYM(rel->r_info); |
|
68 Elf32_Sym * sym = &iDynSymTab[symIdx]; |
|
69 DllSymbol * dllSym = DllSymbolP(sym); |
|
70 if (dllSym) |
|
71 { |
|
72 dllSym->iRel = rel; |
|
73 dllSym->iSegment = iElfFile->GetSegment(SrcSegIdx); |
|
74 if (!AddSymbol(dllSym)) return EFalse; |
|
75 } |
|
76 else errors++; |
|
77 } |
|
78 else if (relType == R_ARM_RABS32) |
|
79 { |
|
80 iNumberOfRelocs++; |
|
81 if (iElfFile->CodeSegmentP(SrcSegIdx)) iNumberOfCodeRelocs++; |
|
82 else iNumberOfDataRelocs++; |
|
83 } |
|
84 else if (relType == R_ARM_RBASE) |
|
85 { |
|
86 SrcSegIdx = ELF32_R_SYM(rel->r_info); |
|
87 if (SrcSegIdx) SrcSegIdx--; |
|
88 } |
|
89 else |
|
90 { |
|
91 // Gives error with all other Relocation types.. |
|
92 TInt symIdx = ELF32_R_SYM(rel->r_info); |
|
93 Elf32_Sym * s = &iDynSymTab[symIdx]; |
|
94 char * symName = ELFADDR(char,iDynStrTab,s->st_name); |
|
95 Print(EPeError, "Unresolved symbol: %s\n", symName); |
|
96 errors++; |
|
97 } |
|
98 } |
|
99 // Set up export info |
|
100 if (InitExportInfo()) |
|
101 { |
|
102 TText * sym = (TText *)"_E32Startup"; |
|
103 // If _E32Startup is defined then this is not a DLL |
|
104 iImageIsDll = !iElfFile->SymbolPresent(sym); |
|
105 } |
|
106 if (errors > 0) return EFalse; |
|
107 return ETrue; |
|
108 } |
|
109 |
|
110 TBool ELFFile::ELFDllData::ParseDllSymbol(Elf32_Sym * s, char *& dll, TUint& len, TInt& ord) |
|
111 { |
|
112 char * sym = ELFADDR(char,iDynStrTab,s->st_name); |
|
113 if (!strncmp(sym, DLLSYMPREFIX, strlen(DLLSYMPREFIX))) |
|
114 { |
|
115 dll = sym + strlen(DLLSYMPREFIX); |
|
116 TUint lim = strlen(dll); |
|
117 TUint index = strcspn(dll, DLLSYMPREFIX0); |
|
118 if ((index + strlen(DLLSYMSUFFIX)) < lim) |
|
119 { |
|
120 len = index; |
|
121 char * dllSuffix = dll+index; |
|
122 char * match = DLLSYMSUFFIX; |
|
123 int suflen = strlen(DLLSYMSUFFIX); |
|
124 if (!strncmp(dllSuffix, match, suflen)) |
|
125 { |
|
126 char * ordString = dll+index+suflen; |
|
127 char * final; |
|
128 TUint X = strtoul(ordString, &final, ORDBASE); |
|
129 if (ordString != final) |
|
130 { |
|
131 ord = (TInt)X; |
|
132 return ETrue; |
|
133 } |
|
134 |
|
135 } |
|
136 } |
|
137 } |
|
138 dll = 0; |
|
139 len = 0; |
|
140 ord = -1; |
|
141 return EFalse; |
|
142 } |
|
143 |
|
144 ELFFile::ELFDllData::DllSymbol * ELFFile::ELFDllData::DllSymbolP(Elf32_Sym * s) |
|
145 { |
|
146 char * dllName; |
|
147 TUint nameLen; |
|
148 TInt symOrd; |
|
149 if (ParseDllSymbol(s, dllName, nameLen, symOrd)) |
|
150 { |
|
151 DllSymbol * ds = new DllSymbol(dllName, nameLen, symOrd); |
|
152 if (ds) return ds; |
|
153 Print(EPeError, "Out of memory.\n"); |
|
154 return NULL; |
|
155 } |
|
156 // If we get here its not a valid 'dll symbol' and so it is an unresolved symbol |
|
157 char * sym = ELFADDR(char,iDynStrTab,s->st_name); |
|
158 Print(EPeError, "Unresolved symbol: %s\n", sym); |
|
159 return NULL; |
|
160 } |
|
161 |
|
162 TBool ELFFile::ELFDllData::AddSymbol(ELFFile::ELFDllData::DllSymbol * s) |
|
163 { |
|
164 DllRec * aDll = NULL; |
|
165 |
|
166 for (DllRec * r = iDllHead; r != NULL; r = r->iNext) |
|
167 { |
|
168 if (!strncmp(s->iDll, r->iName, s->iLen)) |
|
169 { |
|
170 aDll = r; |
|
171 break; |
|
172 } |
|
173 } |
|
174 if (aDll) |
|
175 { |
|
176 iNumberOfImports++; |
|
177 aDll->AddSymbol(s); |
|
178 return ETrue; |
|
179 } |
|
180 else |
|
181 { |
|
182 aDll = new DllRec(s->iDll, s->iLen, s); |
|
183 if (aDll) |
|
184 { |
|
185 if (!iDllHead) |
|
186 { |
|
187 iDllHead = iDllTail = aDll; |
|
188 } |
|
189 else |
|
190 { |
|
191 iDllTail->iNext = aDll; |
|
192 iDllTail = aDll; |
|
193 } |
|
194 iStringTableSize += (s->iLen + 1); |
|
195 iNumberOfImportDlls++; |
|
196 iNumberOfImports++; |
|
197 return ETrue; |
|
198 } |
|
199 else |
|
200 { |
|
201 Print(EPeError, "Out of memory.\n"); |
|
202 return EFalse; |
|
203 } |
|
204 } |
|
205 } |
|
206 |
|
207 void ELFFile::ELFDllData::DllRec::AddSymbol(ELFFile::ELFDllData::DllSymbol * s) |
|
208 { |
|
209 nImports++; |
|
210 iTail->iNext = s; |
|
211 iTail = s; |
|
212 } |
|
213 |
|
214 static unsigned long elf_hash(const unsigned char *name) |
|
215 { |
|
216 unsigned long h, g; |
|
217 for (h = 0; *name != 0; ++name) |
|
218 { |
|
219 h = (h << 4) + *name; |
|
220 g = h & 0xf0000000; |
|
221 if (g != 0) h ^= g >> 24; |
|
222 h &= ~g; |
|
223 } |
|
224 return h; |
|
225 } |
|
226 |
|
227 Elf32_Word ELFFile::ELFDllData::FindSymbolIndex(TText * s) |
|
228 { |
|
229 TUint h = elf_hash(s); |
|
230 TUint nb = iHashTable[0].nBuckets; |
|
231 TUint probe = h%nb; |
|
232 Elf32_Sword * bucket = ELFADDR(Elf32_Sword, iHashTable, sizeof(Elf32_HashTable)); |
|
233 Elf32_Sword * chain = ELFADDR(Elf32_Sword, bucket, nb * sizeof(Elf32_Sword)); |
|
234 Elf32_Sword idx = bucket[probe]; |
|
235 |
|
236 do |
|
237 { |
|
238 if (!strcmp(ELFADDR(char, iDynStrTab, iDynSymTab[idx].st_name), (char *)s)) return idx; |
|
239 idx = chain[idx]; |
|
240 } while (idx > 0); |
|
241 if (idx == 0) idx = -1; |
|
242 return idx; |
|
243 } |
|
244 |
|
245 TBool ELFFile::ELFDllData::InitExportInfo() |
|
246 { |
|
247 memset(&iSymInfoHdr, 0, sizeof(iSymInfoHdr)); |
|
248 TText * exp = (TText *)EXPORTTABLENAME; |
|
249 if ((iExportTableSymIdx = FindSymbolIndex(exp)) != -1) |
|
250 { |
|
251 TText * exps = (TText *)EXPORTTABLESIZENAME; |
|
252 iExportTableSizeSymIdx = FindSymbolIndex(exps); |
|
253 //TUint offset = iDynSymTab[iExportTableSizeSymIdx].st_value - (TUint)code; |
|
254 Elf32_Word * pNumberOfExports = iElfFile->CodePtrFromAddr(iDynSymTab[iExportTableSizeSymIdx].st_value); |
|
255 iNumberOfExports = * pNumberOfExports; |
|
256 iImageIsDll = ETrue; |
|
257 return ETrue; |
|
258 } |
|
259 else iImageIsDll = EFalse; |
|
260 return EFalse; |
|
261 } |
|
262 |
|
263 TInt ELFFile::ELFDllData::NumberOfImports(void) |
|
264 { |
|
265 return iNumberOfImports; |
|
266 } |
|
267 |
|
268 TInt ELFFile::ELFDllData::NumberOfExports(void) |
|
269 { |
|
270 return iNumberOfExports; |
|
271 } |
|
272 |
|
273 TInt ELFFile::ELFDllData::NumberOfImportDlls(void) |
|
274 { |
|
275 return iNumberOfImportDlls; |
|
276 } |
|
277 |
|
278 TInt ELFFile::ELFDllData::NumberOfRelocs() |
|
279 { |
|
280 return iNumberOfRelocs; |
|
281 } |
|
282 |
|
283 char * ELFFile::ELFDllData::CreateImportSection(TInt &aSize) |
|
284 { |
|
285 if (!iNumberOfImports) |
|
286 { |
|
287 aSize = 0; |
|
288 return 0; |
|
289 } |
|
290 |
|
291 TInt byteSize = sizeof(E32ImportSection) + |
|
292 (sizeof(E32ImportBlock) * iNumberOfImportDlls) + |
|
293 (sizeof(TUint) * iNumberOfImports) + |
|
294 iStringTableSize; |
|
295 if(iNamedLookupEnabled) |
|
296 { |
|
297 // 0th ordinal of each DLL imported from. |
|
298 byteSize += (sizeof(TUint) * iNumberOfImportDlls); |
|
299 } |
|
300 char * newSection = new char[byteSize]; |
|
301 |
|
302 if (!newSection) |
|
303 { |
|
304 Print(EPeError, "Failed to allocate new import section.\n"); |
|
305 aSize = 0; |
|
306 return 0; |
|
307 } |
|
308 |
|
309 ((E32ImportSection *)newSection)->iSize = byteSize; |
|
310 |
|
311 // used to point to current ImportBlock |
|
312 E32ImportBlock * bp = ELFADDR(E32ImportBlock, newSection, sizeof(E32ImportSection)); |
|
313 // used to point to current import relocation entry |
|
314 TUint * rp; |
|
315 // used to point to current location in string table |
|
316 char * sp = ELFADDR(char, newSection, (byteSize - iStringTableSize)); |
|
317 OrdZeroRecord *aDep = iDepRecords; |
|
318 |
|
319 for (DllRec * dll = iDllHead; dll != NULL ; dll = dll->iNext, bp = (E32ImportBlock *)rp ) |
|
320 { |
|
321 // set up the offset from E32ImportBlock.iOffsetOfDllName to the |
|
322 // corresponding string table location |
|
323 bp->iOffsetOfDllName = (sp - (char *)newSection); |
|
324 bp->iNumberOfImports = dll->nImports; |
|
325 if(iNamedLookupEnabled) |
|
326 { |
|
327 bp->iNumberOfImports++; |
|
328 } |
|
329 |
|
330 // copy the DLL name to the string table |
|
331 memcpy(sp , dll->iName, dll->iLen); |
|
332 sp[dll->iLen] = 0; |
|
333 sp = sp + dll->iLen + 1; |
|
334 |
|
335 // sort out the import 'relocs' |
|
336 rp = ELFADDR(TUint, bp, sizeof(E32ImportBlock)); |
|
337 |
|
338 for (DllSymbol * sym = dll->iHead; sym != NULL; sym = sym->iNext, rp++) |
|
339 { |
|
340 Elf32_Phdr * segment = sym->iSegment; |
|
341 Elf32_Addr segBase = segment->p_vaddr; |
|
342 |
|
343 // sanity check: segment should be the code segment |
|
344 if (!iElfFile->CodeSegmentP(segment)) |
|
345 { |
|
346 Print(EPeError, "Import relocation does not refer to code segment.\n"); |
|
347 aSize = 0; |
|
348 return 0; |
|
349 } |
|
350 |
|
351 // This field is misnamed because it is actually given as a virtual address in |
|
352 // dynamic relocations |
|
353 Elf32_Addr dynOffset = sym->iRel->r_offset; |
|
354 //So this is the 'real' offset of the reloc in the segment in which it occurs |
|
355 Elf32_Addr segOffset = dynOffset - segBase; |
|
356 TUint * relocAddr = ELFADDR(TUint, iElfFile->ELFFileBase(), (segment->p_offset + segOffset)); |
|
357 // The only non-zero reloc vals we expect are for vtables. |
|
358 // We store there reloc offset in the top 16 bits of the 'reloc info'. |
|
359 // NB the ELF reloc values should only ever be multiples of 4. So we could optimize here, |
|
360 // but we won't. |
|
361 TUint relocVal = *relocAddr; |
|
362 TUint importOrdinal = sym->iOrd; |
|
363 if (relocVal > 0xFFFF) |
|
364 Print(EPeError, "ELF relocation exceeds E32Image limit of 64K.\n"); |
|
365 if (importOrdinal > 0xFFFF) |
|
366 Print(EPeError, "Import ordinal exceeds E32Image limit of 64K.\n"); |
|
367 |
|
368 *rp = segOffset; |
|
369 |
|
370 // eek !! surgery on the code segment.... |
|
371 *relocAddr = (relocVal<<16) | importOrdinal; |
|
372 } |
|
373 |
|
374 if(iNamedLookupEnabled) |
|
375 { |
|
376 aDep = FindDependency(dll->iName, dll->iLen); |
|
377 if( aDep ) |
|
378 { |
|
379 *rp = aDep->iOffset; |
|
380 rp++; |
|
381 } |
|
382 } |
|
383 } |
|
384 |
|
385 aSize = byteSize; |
|
386 return newSection; |
|
387 } |
|
388 |
|
389 TUint ELFFile::ELFDllData::GetExportTableOffset(void) |
|
390 { |
|
391 Elf32_Sym * et = &iDynSymTab[iExportTableSymIdx]; |
|
392 Elf32_Phdr * segment = iElfFile->GetSegment(et->st_shndx - 1); |
|
393 |
|
394 return et->st_value - segment->p_vaddr; |
|
395 } |
|
396 |
|
397 TBool ELFFile::ELFDllData::GetRelocs(Elf32_Rel **aCodeRelocs, Elf32_Rel **aDataRelocs) |
|
398 // |
|
399 // load the relocs from the reloc section into relocation and relocsection arrays |
|
400 // |
|
401 { |
|
402 TInt nrelocs = iRelSz/iRelEnt; |
|
403 |
|
404 TInt SrcSegIdx = -1; |
|
405 |
|
406 for (TInt idx = 0, cidx = 0, didx = 0; idx < nrelocs; idx++) |
|
407 { |
|
408 Elf32_Rel * rel = &iRel[idx]; |
|
409 |
|
410 if (ELF32_R_TYPE(rel->r_info) == R_ARM_RABS32) |
|
411 { |
|
412 if (iElfFile->CodeSegmentP(SrcSegIdx)) |
|
413 aCodeRelocs[cidx++]=rel; |
|
414 else if (iElfFile->DataSegmentP(SrcSegIdx)) |
|
415 aDataRelocs[didx++]=rel; |
|
416 } |
|
417 else if (ELF32_R_TYPE(rel->r_info) == R_ARM_RBASE) |
|
418 { |
|
419 SrcSegIdx = ELF32_R_SYM(rel->r_info); |
|
420 if (!(iElfFile->CodeSegmentP(SrcSegIdx-1) || iElfFile->DataSegmentP(SrcSegIdx-1))) |
|
421 { |
|
422 Print(EPeError, "Source segment for relocations is neither Code or Data.\n"); |
|
423 return EFalse; |
|
424 } |
|
425 SrcSegIdx--; |
|
426 } |
|
427 } |
|
428 if(!iNamedLookupEnabled) |
|
429 return ETrue; |
|
430 |
|
431 // Add the 0th ordinal of this binary - The relocation info is already setup. |
|
432 aCodeRelocs[cidx++] = &iOrdZeroRec->iReloc; |
|
433 |
|
434 // add relocation entries for each of the symbols |
|
435 NamedExportSymbol *aSym = iNamedExportSymbolHead; |
|
436 while(aSym) |
|
437 { |
|
438 // The symbol name info is part of the code section hence all relocations |
|
439 // are collected as part of Code relocations. |
|
440 aCodeRelocs[cidx++] = &aSym->iReloc; |
|
441 aSym = aSym->Next(); |
|
442 } |
|
443 |
|
444 // Since we have added a few relocations, lets make sure |
|
445 // they are still sorted on addresses they refer to. |
|
446 |
|
447 //Sorting the code relocs |
|
448 TInt aIdx1, aIdx2; |
|
449 Elf32_Rel *aTmp; |
|
450 for (aIdx1 = 0; aIdx1 < cidx; aIdx1++) { |
|
451 for (aIdx2 = aIdx1; aIdx2 < cidx; aIdx2++) { |
|
452 if(aCodeRelocs[aIdx1]->r_offset > aCodeRelocs[aIdx2]->r_offset) { |
|
453 aTmp = aCodeRelocs[aIdx2]; |
|
454 aCodeRelocs[aIdx2] = aCodeRelocs[aIdx1]; |
|
455 aCodeRelocs[aIdx1] = aTmp; |
|
456 } |
|
457 } |
|
458 } |
|
459 |
|
460 //Sorting the data relocs |
|
461 for (aIdx1 = 0; aIdx1 < didx; aIdx1++) { |
|
462 for (aIdx2 = aIdx1; aIdx2 < didx; aIdx2++) { |
|
463 if(aDataRelocs[aIdx1]->r_offset > aDataRelocs[aIdx2]->r_offset) { |
|
464 aTmp = aDataRelocs[aIdx2]; |
|
465 aDataRelocs[aIdx2] = aDataRelocs[aIdx1]; |
|
466 aDataRelocs[aIdx1] = aTmp; |
|
467 } |
|
468 } |
|
469 } |
|
470 |
|
471 return ETrue; |
|
472 } |
|
473 |
|
474 NamedExportSymbol::NamedExportSymbol(char* aName, Elf32_Addr aValue) : \ |
|
475 iSymbolName(aName), iValue(aValue), iNext(NULL) |
|
476 { |
|
477 } |
|
478 |
|
479 TBool ELFFile::ELFDllData::CreateSymLookupTable() |
|
480 { |
|
481 if( !SetupSymbolValues() ) |
|
482 return FALSE; |
|
483 |
|
484 if( !SetupSymbolNames() ) |
|
485 return FALSE; |
|
486 |
|
487 return TRUE; |
|
488 } |
|
489 |
|
490 TBool ELFFile::ELFDllData::SetupSymbolValues() |
|
491 { |
|
492 NamedExportSymbol *aSym, *aPrevSym; |
|
493 |
|
494 if( iExportTableSymIdx == -1 || iExportTableSizeSymIdx == -1) |
|
495 return FALSE; |
|
496 |
|
497 // Fetch the 'export table' symbol from the dynamic symbol table. |
|
498 Elf32_Sym *aElfExpTbl = &iDynSymTab[iExportTableSymIdx]; |
|
499 |
|
500 // Fetch the 'export table size' symbol from the dynamic symbol table. |
|
501 Elf32_Sym *aElfExpTblSz = &iDynSymTab[iExportTableSizeSymIdx]; |
|
502 |
|
503 if((aElfExpTbl->st_value - aElfExpTblSz->st_value) != 4) |
|
504 { |
|
505 // Check that the word prior to the export table is not the export table size |
|
506 // This is to make sure that there is space for the 0th ordinal and |
|
507 // we dont overwrite the 'export table size' entry. |
|
508 iNamedLookupEnabled = 1; |
|
509 } |
|
510 else |
|
511 return FALSE; |
|
512 |
|
513 // Fetch the export table contents |
|
514 Elf32_Word * aExpEntries = iElfFile->CodePtrFromAddr(aElfExpTbl->st_value); |
|
515 |
|
516 if(!aExpEntries) |
|
517 return FALSE; |
|
518 |
|
519 aSym = aPrevSym = NULL; |
|
520 TInt idx; |
|
521 // Create symbols corresponding to export table entries. |
|
522 for(idx = 0; idx < iNumberOfExports; idx++) |
|
523 { |
|
524 //Symbols marked Absent are ignored. |
|
525 if( aExpEntries[idx] == iElfFile->iEntryPoint) |
|
526 continue; |
|
527 |
|
528 aSym = new NamedExportSymbol(0, aExpEntries[idx]); |
|
529 iNamedExportCount++; |
|
530 if(aPrevSym) |
|
531 { |
|
532 aPrevSym->Next(aSym); |
|
533 } |
|
534 else |
|
535 { |
|
536 iNamedExportSymbolHead = aSym; |
|
537 } |
|
538 |
|
539 aPrevSym = aSym; |
|
540 } |
|
541 |
|
542 return TRUE; |
|
543 } |
|
544 |
|
545 TBool ELFFile::ELFDllData::SetupSymbolNames() |
|
546 { |
|
547 char *aSymName = NULL; |
|
548 NamedExportSymbol *aSym; |
|
549 TUint aDynSymbolTblCount = iHashTable->nChains; |
|
550 TInt aCount = 0; |
|
551 TInt aCodeSegIdx = iElfFile->CodeSegmentIndex() + 1; |
|
552 TInt aDataSegIdx = iElfFile->DataSegmentIndex() + 1; |
|
553 |
|
554 // Traverse the dynamic symbol table |
|
555 for(TUint idx = 0; idx < aDynSymbolTblCount; idx++) |
|
556 { |
|
557 //Consider only the the defined symbols |
|
558 if( ELF32_ST_TYPE(iDynSymTab[idx].st_info) == STT_OBJECT || |
|
559 ELF32_ST_TYPE(iDynSymTab[idx].st_info) == STT_FUNC ) |
|
560 { |
|
561 aSym = iNamedExportSymbolHead; |
|
562 while(aSym) |
|
563 { |
|
564 // Name already set |
|
565 if(aSym->Name()) |
|
566 { |
|
567 aSym = aSym->Next(); |
|
568 continue; |
|
569 } |
|
570 Elf32_Addr aAddr = aSym->Value(); |
|
571 |
|
572 // If the exported symbol and the dynamic symbol table entry have the |
|
573 // same values, setup the name |
|
574 if(iDynSymTab[idx].st_value == aAddr) |
|
575 { |
|
576 aSymName = ELFADDR(char, iDynStrTab, iDynSymTab[idx].st_name); |
|
577 aSym->Name(aSymName); |
|
578 |
|
579 if(iElfFile->CodeSegmentP (iElfFile->GetSegmentFromAddr(aAddr)) ) { |
|
580 aSym->iReloc.r_info = aCodeSegIdx << 8 | R_ARM_RABS32; |
|
581 aSym->iSymRelocType = KTextRelocType; |
|
582 } |
|
583 else { |
|
584 aSym->iReloc.r_info = aDataSegIdx << 8 | R_ARM_RABS32; |
|
585 aSym->iSymRelocType = KDataRelocType; |
|
586 } |
|
587 |
|
588 iNumberOfCodeRelocs++; |
|
589 iNumberOfRelocs++; |
|
590 |
|
591 // The offset to the name is always 4 byte aligned. |
|
592 iStringNameOffset = iSymStringTableSize >> 2; |
|
593 aSym->NameOffset( iSymStringTableSize ); |
|
594 // These are NULL-terminated strings |
|
595 iSymStringTableSize += (strlen(aSymName) + 1); |
|
596 iSymStringTableSize = ALIGN4(iSymStringTableSize); |
|
597 |
|
598 aCount++; |
|
599 break; |
|
600 } |
|
601 aSym = aSym->Next(); |
|
602 } |
|
603 } |
|
604 } |
|
605 |
|
606 if(aCount != iNamedExportCount) |
|
607 return FALSE; |
|
608 |
|
609 // Sort symbols on their names... |
|
610 if(iNamedExportCount > 1) |
|
611 { |
|
612 NamedExportSymbol **aTmpStart = &iNamedExportSymbolHead; |
|
613 Sort(aTmpStart, iNamedExportSymbolHead); |
|
614 } |
|
615 |
|
616 return TRUE; |
|
617 } |
|
618 |
|
619 void ELFFile::ELFDllData::SetLookupTblBase(TInt aBaseOffset) |
|
620 { |
|
621 Elf32_Addr aBaseAddr = iElfFile->iLinkedBase + iElfFile->GetCodeSize(); |
|
622 |
|
623 Elf32_Addr aAddr; |
|
624 |
|
625 // setup relocations of each of the exported symbols. |
|
626 aAddr = aBaseAddr + iSymInfoHdr.iSymbolTblOffset; |
|
627 NamedExportSymbol *aSym = iNamedExportSymbolHead; |
|
628 while(aSym) |
|
629 { |
|
630 aSym->iReloc.r_offset = aAddr; |
|
631 aAddr += sizeof(Elf32_Addr); |
|
632 aSym = aSym->Next(); |
|
633 } |
|
634 |
|
635 // setup relocations for the 0th ordinal of this binary. |
|
636 |
|
637 iOrdZeroRec = new OrdZeroRecord(0); |
|
638 Elf32_Sym * et = &iDynSymTab[iExportTableSymIdx]; |
|
639 iOrdZeroRec->iReloc.r_offset = et->st_value - 4; // The word prior ro the first entry |
|
640 // of the export table is the 0th ordinal entry. |
|
641 |
|
642 //At the 0th ordinal, write the address of the start of symbol info |
|
643 TUint32 aZeroOrdOff = et->st_value - 4 - iElfFile->iLinkedBase; |
|
644 aZeroOrdOff += (iElfFile->GetSegment(et->st_shndx - 1))->p_offset; |
|
645 TUint32 *aZeroOrdLocation = ELFADDR(TUint32, iElfFile->ELFFileBase(), aZeroOrdOff); |
|
646 *aZeroOrdLocation = aBaseAddr; |
|
647 |
|
648 iOrdZeroRec->iReloc.r_info = ELF32_R_INFO(et->st_shndx, R_ARM_RABS32); |
|
649 iNumberOfCodeRelocs++; |
|
650 iNumberOfRelocs++; |
|
651 |
|
652 TInt aOffset = aBaseOffset + iSymInfoHdr.iDepDllZeroOrdTableOffset; |
|
653 |
|
654 OrdZeroRecord *aDepRecord = iDepRecords; |
|
655 |
|
656 while( aDepRecord ) |
|
657 { |
|
658 // Setup the offset - This offset (relative code segment) is filled in the |
|
659 // import table to point to this dependency record. |
|
660 aDepRecord->iOffset = aOffset; |
|
661 |
|
662 aOffset += 4; |
|
663 aDepRecord = aDepRecord->iNext; |
|
664 } |
|
665 } |
|
666 |
|
667 TBool ELFFile::ELFDllData::AddToDependency(TUint aOff) |
|
668 { |
|
669 // Add the name found in DT_NEEDED into a list. |
|
670 // The dynamic string table might not have been found in dynamic table yet. |
|
671 // So store the offset (wrt base of dynamic string table) for now. |
|
672 NeededDLLsList *aNeeded = new NeededDLLsList(aOff); |
|
673 if(!aNeeded) |
|
674 return FALSE; |
|
675 |
|
676 if ( iNeededDllNames ) { |
|
677 iNeededDllNamesTail->iNext= aNeeded; |
|
678 iNeededDllNamesTail = aNeeded; |
|
679 } |
|
680 else { |
|
681 iNeededDllNames = iNeededDllNamesTail = aNeeded; |
|
682 } |
|
683 |
|
684 return TRUE; |
|
685 } |
|
686 |
|
687 TBool ELFFile::ELFDllData::CreateDependency() |
|
688 { |
|
689 OrdZeroRecord *aDep; |
|
690 NeededDLLsList *aNeeded = iNeededDllNames; |
|
691 char *aDllName = NULL; |
|
692 DllRec *aRec; |
|
693 TInt aNeededFound; |
|
694 |
|
695 for(aNeededFound = 0; (aNeededFound < iNumberOfImportDlls) && aNeeded;) |
|
696 { |
|
697 aRec = 0; |
|
698 while(aNeeded) { |
|
699 aDllName = iDynStrTab + aNeeded->iOffset; |
|
700 // aNeeded is just a guess that this binary might be dependent on aDllName |
|
701 // Search through the import table to find if the guess was correct. |
|
702 aRec = SearchImports(aDllName); |
|
703 if(aRec && FindDependency(aRec->iName, aRec->iLen) == NULL) { |
|
704 // Check if aDllName is listed in import table and it |
|
705 // not added already in the depedency records. |
|
706 aNeededFound++; |
|
707 break; |
|
708 } |
|
709 // Bad guess...go to the next aNeeded |
|
710 aNeeded = aNeeded->iNext; |
|
711 } |
|
712 |
|
713 if( !aRec ) |
|
714 return FALSE; |
|
715 |
|
716 aDep = new OrdZeroRecord(aDllName); |
|
717 if(!iDepRecords) |
|
718 { |
|
719 iDepRecords = iDepRecordsTail = aDep; |
|
720 } |
|
721 else |
|
722 { |
|
723 iDepRecordsTail->iNext = aDep; |
|
724 iDepRecordsTail = aDep; |
|
725 } |
|
726 aNeeded = aNeeded->iNext; |
|
727 } |
|
728 |
|
729 return (aNeededFound == iNumberOfImportDlls); |
|
730 } |
|
731 |
|
732 ELFFile::ELFDllData::DllRec* ELFFile::ELFDllData::SearchImports(char *aName) |
|
733 { |
|
734 DllRec *aRec = iDllHead; |
|
735 while (aRec) |
|
736 { |
|
737 if(strncmp(aRec->iName, aName, aRec->iLen) == 0) |
|
738 return aRec; |
|
739 aRec = aRec->iNext; |
|
740 } |
|
741 return NULL; |
|
742 } |
|
743 |
|
744 OrdZeroRecord* ELFFile::ELFDllData::FindDependency(char* aName, TUint aLen) |
|
745 { |
|
746 OrdZeroRecord* aDep = iDepRecords; |
|
747 while(aDep) |
|
748 { |
|
749 if(strncmp(aName, aDep->iName, aLen) == 0) |
|
750 return aDep; |
|
751 aDep = aDep->iNext; |
|
752 } |
|
753 return NULL; |
|
754 } |
|
755 |
|
756 void ELFFile::ELFDllData::GetExportSymInfoHeader(E32EpocExpSymInfoHdr& aSymInfoHdr) |
|
757 { |
|
758 memcpy(&aSymInfoHdr, &iSymInfoHdr, sizeof(E32EpocExpSymInfoHdr)); |
|
759 } |
|
760 |
|
761 void ELFFile::ELFDllData::SetExportSymInfo() |
|
762 { |
|
763 iSymInfoHdr.iSymCount = (TUint16)iNamedExportCount; |
|
764 iSymInfoHdr.iSymbolTblOffset = sizeof(E32EpocExpSymInfoHdr); |
|
765 iSymInfoHdr.iStringTableSz = iSymStringTableSize; |
|
766 TInt aSymTabSz; |
|
767 if( iStringNameOffset > 0xffff){ |
|
768 iSymInfoHdr.iFlags = KNameLookupOffsetFlag32; // Flag indicating 32 bit offsets |
|
769 // for symbol names |
|
770 aSymTabSz = iNamedExportCount* sizeof(TUint32);// symbol addresses |
|
771 aSymTabSz += iNamedExportCount* sizeof(TUint32);// symbol name 32-bit offsets |
|
772 } |
|
773 else |
|
774 { |
|
775 iSymInfoHdr.iFlags &= ~KNameLookupOffsetFlag32;// Flag indicating 16-bit offsets |
|
776 // for symbol names |
|
777 aSymTabSz = iNamedExportCount* sizeof(TUint32); // symbol addresses |
|
778 aSymTabSz += iNamedExportCount* sizeof(TUint16);// symbol name 16-bit offsets |
|
779 aSymTabSz = ALIGN4(aSymTabSz); |
|
780 } |
|
781 iSymInfoHdr.iStringTableOffset = iSymInfoHdr.iSymbolTblOffset + aSymTabSz; |
|
782 iSymInfoHdr.iDllCount = iNumberOfImportDlls; |
|
783 iSymInfoHdr.iDepDllZeroOrdTableOffset = iSymInfoHdr.iStringTableOffset + \ |
|
784 iSymInfoHdr.iStringTableSz; |
|
785 |
|
786 iSymInfoHdr.iSize = iSymInfoHdr.iDepDllZeroOrdTableOffset + \ |
|
787 iSymInfoHdr.iDllCount * sizeof(Elf32_Addr); |
|
788 } |
|
789 |
|
790 TUint ELFFile::ELFDllData::GetSymLookupSection(char* aBuff) |
|
791 { |
|
792 if( !iNamedLookupEnabled) |
|
793 return 0; |
|
794 |
|
795 memcpy(aBuff, &iSymInfoHdr, sizeof(iSymInfoHdr)); |
|
796 |
|
797 // Name offsets start after the end of symbol addresses. |
|
798 TUint32 aNameOffsetStart = iSymInfoHdr.iSymbolTblOffset + \ |
|
799 iNamedExportCount* sizeof(TUint32); |
|
800 |
|
801 TUint32 *aAddrPtr = (TUint32*)(aBuff + iSymInfoHdr.iSymbolTblOffset); |
|
802 TUint32 aStringTabOff = 0; |
|
803 char *aStringTab = aBuff + iSymInfoHdr.iStringTableOffset;//Start of the string table. |
|
804 NamedExportSymbol *aSym = iNamedExportSymbolHead; |
|
805 while(aSym) |
|
806 { |
|
807 *aAddrPtr = aSym->Value(); |
|
808 aStringTabOff = aSym->NameOffset(); // Get the offset of symbol name (which is wrt |
|
809 // string table base). |
|
810 if( iSymInfoHdr.iFlags & KNameLookupOffsetFlag32 ) |
|
811 { |
|
812 TUint32 *aNameOffPtr = (TUint32*)(aBuff + aNameOffsetStart); |
|
813 *aNameOffPtr = (aStringTabOff >> 2);//write the offset of the name |
|
814 strcpy(aStringTab + aStringTabOff, aSym->Name());//write the symbol name |
|
815 aNameOffsetStart +=4; |
|
816 } |
|
817 else |
|
818 { |
|
819 TUint16 *aNameOffPtr = (TUint16*)(aBuff + aNameOffsetStart); |
|
820 *aNameOffPtr = (TUint16)(aStringTabOff >> 2);//write the offset of the name |
|
821 strcpy(aStringTab + aStringTabOff, aSym->Name());//write the symbol name |
|
822 aNameOffsetStart +=2; |
|
823 } |
|
824 aAddrPtr++; |
|
825 aSym = aSym->Next(); |
|
826 } |
|
827 |
|
828 OrdZeroRecord *aRec = iDepRecords; |
|
829 TUint32* aDepsTable = (TUint32*)(aBuff + iSymInfoHdr.iDepDllZeroOrdTableOffset); |
|
830 while(aRec) |
|
831 { |
|
832 *aDepsTable++ = 0; |
|
833 aRec = aRec->iNext; |
|
834 } |
|
835 return iSymInfoHdr.iSize; |
|
836 } |
|
837 |
|
838 void ELFFile::ELFDllData::Sort(NamedExportSymbol** aDstList, NamedExportSymbol* aSrcList) |
|
839 { |
|
840 NamedExportSymbol *aSym = aSrcList; |
|
841 NamedExportSymbol **aSymbols = new NamedExportSymbol*[iNamedExportCount]; |
|
842 |
|
843 TInt pos; |
|
844 for (pos = 0; pos < iNamedExportCount; pos++) { |
|
845 aSymbols[pos] = aSym; |
|
846 aSym = aSym->Next(); |
|
847 } |
|
848 |
|
849 NamedExportSymbol **aResult = new NamedExportSymbol*[iNamedExportCount]; |
|
850 MergeSort(aResult, aSymbols); |
|
851 iNamedExportSymbolHead = aResult[0]; |
|
852 for (pos = 0; pos < iNamedExportCount; pos++) { |
|
853 aSym = aResult[pos]; |
|
854 if( pos == iNamedExportCount-1) |
|
855 aSym->Next(NULL); |
|
856 else |
|
857 aSym->Next(aResult[pos+1]); |
|
858 } |
|
859 *aDstList = aResult[0]; |
|
860 delete [] aResult; |
|
861 delete [] aSymbols; |
|
862 } |
|
863 |
|
864 void ELFFile::ELFDllData::MergeSort(NamedExportSymbol** aDstList, NamedExportSymbol** aSrcList) |
|
865 { |
|
866 MergeSort(aDstList, aSrcList, 0, iNamedExportCount); |
|
867 } |
|
868 |
|
869 void ELFFile::ELFDllData::MergeSort(NamedExportSymbol** aDstList, NamedExportSymbol** aSrcList, \ |
|
870 TUint aLeft, TUint aRight) |
|
871 { |
|
872 if( (aRight - aLeft) <= 1) |
|
873 return; |
|
874 |
|
875 TUint aSize = aRight - aLeft; |
|
876 TUint aCenter = aLeft + aSize/2; |
|
877 |
|
878 MergeSort(aDstList, aSrcList, aLeft, aCenter); |
|
879 MergeSort(aDstList, aSrcList, aCenter, aRight); |
|
880 |
|
881 TUint aLPos, aRPos, aCnt; |
|
882 aLPos = aLeft; |
|
883 aRPos = aCenter; |
|
884 for(aCnt = 0; aCnt < aSize; aCnt++) |
|
885 { |
|
886 if( (aLPos < aCenter) && |
|
887 (aRPos == aRight || (strcmp(aSrcList[aLPos]->Name(), aSrcList[aRPos]->Name()) < 0) ) |
|
888 ) |
|
889 { |
|
890 // Compare the left half with the right and add the lesser one. |
|
891 // The comparision is done on the topmost element on each half. |
|
892 // if aRPos is past the last element of the right half, the left element has |
|
893 // nothing to compare with. Just add it to the result list. |
|
894 aDstList[aCnt] = aSrcList[aLPos]; |
|
895 aLPos++; |
|
896 } |
|
897 else |
|
898 { |
|
899 // Add the greater one into the list. |
|
900 // if aLPos is past the element at the center, it anyway belongs to the |
|
901 // right half. Add it to the result list. |
|
902 aDstList[aCnt] = aSrcList[aRPos]; |
|
903 aRPos++; |
|
904 } |
|
905 } |
|
906 |
|
907 // Once the sublist is sorted, put it back to the source list |
|
908 // so that the parent has its left and right sublists are sorted. |
|
909 for(aCnt = 0; aCnt < aSize; aCnt++) |
|
910 { |
|
911 aSrcList[aLeft+aCnt] = aDstList[aCnt]; |
|
912 } |
|
913 } |
|
914 |