|
1 /* |
|
2 * Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <time.h> |
|
20 #include <malloc.h> |
|
21 #include <string.h> |
|
22 #include "elftran.h" |
|
23 #include <e32std.h> |
|
24 #include <elfdefs.h> |
|
25 #include "elffile.h" |
|
26 #include <h_ver.h> |
|
27 #include <h_utl.h> |
|
28 |
|
29 extern TUid gUid1, gUid2, gUid3; |
|
30 extern int gSetUid1, gSetUid2, gSetUid3; |
|
31 |
|
32 int gAlignConstSection=FALSE; |
|
33 TUint gConstSectionAddressMask=0; |
|
34 |
|
35 E32ImageFile* E32ImageFile::New() |
|
36 { |
|
37 return new E32ImageFile_ELF; |
|
38 } |
|
39 |
|
40 E32ImageFile_ELF::E32ImageFile_ELF() |
|
41 { |
|
42 } |
|
43 |
|
44 E32ImageFile_ELF::~E32ImageFile_ELF() |
|
45 { |
|
46 } |
|
47 |
|
48 TInt E32ImageFile_ELF::DoCodeHeader(ELFFile &aElfFile) |
|
49 // |
|
50 // Calculate the code parts of the ELFFile |
|
51 // |
|
52 { |
|
53 |
|
54 TInt size=ALIGN4(aElfFile.GetCodeSize()); |
|
55 iHdr->iCodeSize = iHdr->iTextSize = size; |
|
56 // make it the offset from the beginning of the file..... |
|
57 if(iHdr->iExportDirCount==0) |
|
58 iHdr->iExportDirOffset = 0; |
|
59 else |
|
60 iHdr->iExportDirOffset = aElfFile.GetExportTableOffset() + iHdr->iCodeOffset; |
|
61 |
|
62 return size; |
|
63 } |
|
64 |
|
65 TInt E32ImageFile_ELF::DoDataHeader(ELFFile &aElfFile, TUint aDataBase) |
|
66 { |
|
67 |
|
68 if (aDataBase==0 && aElfFile.iDataSegmentHdr) |
|
69 aDataBase=aElfFile.iDataSegmentHdr->p_vaddr; |
|
70 TInt size=0; |
|
71 |
|
72 iHdr->iDataBase=aDataBase; |
|
73 |
|
74 if (aElfFile.HasInitialisedData()) |
|
75 { |
|
76 size=ALIGN4(aElfFile.GetDataSize()); |
|
77 iHdr->iDataOffset = iHdr->iCodeOffset + iHdr->iCodeSize; |
|
78 iHdr->iDataSize = size; |
|
79 } |
|
80 if (aElfFile.HasBssData()) |
|
81 { |
|
82 iHdr->iBssSize = ALIGN4(aElfFile.GetBssSize()); |
|
83 } |
|
84 return size; |
|
85 } |
|
86 |
|
87 TInt E32ImageFile_ELF::CopyCode(char *p, ELFFile &aElfFile) |
|
88 // |
|
89 // Copies the files code sections to p |
|
90 // returns the number of bytes copied or KErrGeneral |
|
91 // |
|
92 { |
|
93 TInt size=aElfFile.GetCodeSize(); |
|
94 memcpy(p, (char *)aElfFile.GetCode(), size); |
|
95 p+=ALIGN4(size); |
|
96 return iHdr->iCodeSize = size; |
|
97 } |
|
98 |
|
99 TInt E32ImageFile_ELF::CopyData(char *p, ELFFile &aElfFile) |
|
100 { |
|
101 TInt size=aElfFile.GetDataSize(); |
|
102 if (size) memcpy(p, (char *)aElfFile.GetData(), size); |
|
103 return size; |
|
104 } |
|
105 |
|
106 TInt E32ImageFile_ELF::Translate(const char* aFileName, TUint aDataBase, TBool aAllowDllData, \ |
|
107 TBool aSymLkupEnabled) |
|
108 // |
|
109 // Translate a ELF format file to a E32Image file |
|
110 // |
|
111 |
|
112 { |
|
113 iSource = EElfFile; |
|
114 ELFFile elffile; |
|
115 if (!elffile.Init((const TText * const)aFileName)) return KErrGeneral; |
|
116 |
|
117 iFileName = strdup(aFileName); |
|
118 |
|
119 Adjust(ALIGN4(sizeof(E32ImageHeaderV))); // fixed for now because holes not supported |
|
120 SetDefaultHeader(); |
|
121 iHdr->iDllRefTableCount = elffile.NumberOfImportDlls(); |
|
122 iHdr->iExportDirCount = elffile.NumberOfExports(); |
|
123 iHdr->iCodeBase = elffile.iLinkedBase; |
|
124 |
|
125 if(aSymLkupEnabled) |
|
126 { |
|
127 if( !SetUpLookupTable(elffile) ) |
|
128 return KErrGeneral; |
|
129 } |
|
130 |
|
131 |
|
132 TInt size = ALIGN4(sizeof(E32ImageHeaderV)); // fixed for now because holes not supported |
|
133 iHdr->iCodeOffset = size; |
|
134 TInt pos = size; |
|
135 size+=DoCodeHeader(elffile); |
|
136 |
|
137 size += DoSymbolLookupHeader(elffile, size - pos); |
|
138 |
|
139 TInt nimports=elffile.NumberOfImports(); |
|
140 TInt importSectionSize; |
|
141 char *newImportSection=CreateImportSection(elffile, importSectionSize); |
|
142 |
|
143 TInt t=DoDataHeader(elffile, aDataBase); |
|
144 if (t>0) |
|
145 { |
|
146 iHdr->iDataOffset = size; |
|
147 size += t; |
|
148 } |
|
149 if (importSectionSize!=0) |
|
150 { |
|
151 iHdr->iImportOffset=size; |
|
152 size+=ALIGN4(importSectionSize); |
|
153 } |
|
154 |
|
155 char *newCodeRelocs=NULL; |
|
156 char *newDataRelocs=NULL; |
|
157 TInt codeRelocSize=0, dataRelocSize=0; |
|
158 TInt nCodeRelocs=elffile.NumberOfCodeRelocs(); |
|
159 TInt nDataRelocs=elffile.NumberOfDataRelocs(); |
|
160 if (nCodeRelocs + nDataRelocs) |
|
161 { |
|
162 Elf32_Rel **codeRelocs=new Elf32_Rel * [nCodeRelocs]; |
|
163 Elf32_Rel **dataRelocs=new Elf32_Rel * [nDataRelocs]; |
|
164 if (!elffile.GetRelocs(codeRelocs, dataRelocs)) return KErrGeneral; |
|
165 |
|
166 FixRelocs(elffile, codeRelocs, dataRelocs); |
|
167 if (elffile.iCodeSegmentHdr) |
|
168 newCodeRelocs=CreateRelocs(elffile, codeRelocs, nCodeRelocs, codeRelocSize, elffile.iCodeSegmentHdr->p_vaddr); |
|
169 if (elffile.iDataSegmentHdr) |
|
170 newDataRelocs=CreateRelocs(elffile, dataRelocs, nDataRelocs, dataRelocSize, elffile.iDataSegmentHdr->p_vaddr); |
|
171 if (codeRelocSize) |
|
172 { |
|
173 iHdr->iCodeRelocOffset = size; |
|
174 size += codeRelocSize; |
|
175 } |
|
176 if (dataRelocSize) |
|
177 { |
|
178 iHdr->iDataRelocOffset = size; |
|
179 size += dataRelocSize; |
|
180 } |
|
181 delete [] codeRelocs; |
|
182 delete [] dataRelocs; |
|
183 } |
|
184 |
|
185 Adjust(size); |
|
186 t=CopyCode(iData + pos, elffile); |
|
187 if (t<0) |
|
188 return KErrGeneral; |
|
189 pos += t; |
|
190 t = CopyExportSymInfo(iData+pos, elffile); |
|
191 if (t<0) |
|
192 return KErrGeneral; |
|
193 pos += t; |
|
194 |
|
195 pos += CopyData(iData + pos, elffile); |
|
196 if (nimports) |
|
197 { |
|
198 memcpy(iData + pos, newImportSection, importSectionSize); |
|
199 pos += ALIGN4(importSectionSize); |
|
200 } |
|
201 if (codeRelocSize) |
|
202 { |
|
203 memcpy(iData + pos, newCodeRelocs, codeRelocSize); |
|
204 pos += codeRelocSize; |
|
205 } |
|
206 if (dataRelocSize) |
|
207 { |
|
208 memcpy(iData + pos, newDataRelocs, dataRelocSize); |
|
209 pos += dataRelocSize; |
|
210 } |
|
211 |
|
212 // locate the entry point |
|
213 TUint entryPointOffset=elffile.GetEntryPointOffset(); |
|
214 |
|
215 // Arrange a header for this E32 Image |
|
216 iHdr->iCpuIdentifier = (TUint16)ECpuArmV4; |
|
217 // Import format is ELF-derived |
|
218 iHdr->iFlags |= KImageImpFmt_ELF; |
|
219 // ABI is ARM EABI |
|
220 iHdr->iFlags |= KImageABI_EABI; |
|
221 if (ImageIsDll(elffile)) |
|
222 { |
|
223 iHdr->iFlags |= KImageDll; |
|
224 if (iHdr->iDataSize && !aAllowDllData) |
|
225 return Print(EError, "Dll '%s' has initialised data.\n", iFileName); |
|
226 if (iHdr->iBssSize && !aAllowDllData) |
|
227 return Print(EError, "Dll '%s' has uninitialised data.\n", iFileName); |
|
228 } |
|
229 iHdr->iHeapSizeMin = elffile.iHeapCommittedSize; |
|
230 iHdr->iHeapSizeMax = elffile.iHeapReservedSize; |
|
231 iHdr->iStackSize = elffile.iStackCommittedSize; |
|
232 iHdr->iEntryPoint = entryPointOffset; |
|
233 TInt r = DetermineEntryPointType(); |
|
234 if (r == KErrCorrupt) |
|
235 return Print(EError, "File '%s': Bad Entry Point.\n", iFileName); |
|
236 else if (r == KErrNotSupported) |
|
237 return Print(EError, "File '%s': Bad Entry Point Type.\n", iFileName); |
|
238 |
|
239 SetUpExceptions(elffile); |
|
240 |
|
241 delete [] newImportSection; |
|
242 delete [] newCodeRelocs; |
|
243 delete [] newDataRelocs; |
|
244 |
|
245 return KErrNone; |
|
246 } |
|
247 |
|
248 TBool E32ImageFile_ELF::Translate(ELFFile &aElfFile) |
|
249 { |
|
250 // VT fix for warning |
|
251 // fix warning in Linux |
|
252 return Translate((const char*)aElfFile.iFileName, 0, EFalse); |
|
253 } |
|
254 |
|
255 TBool E32ImageFile_ELF::ImageIsDll(ELFFile& aElfFile) |
|
256 { |
|
257 return aElfFile.ImageIsDll(); |
|
258 } |
|
259 |
|
260 void E32ImageFile_ELF::SetUpExceptions(ELFFile &aElfFile) |
|
261 { |
|
262 aElfFile.GetExceptionIndexInfo(iHdr->iExceptionDescriptor); |
|
263 } |
|
264 |
|
265 void E32ImageFile_ELF::SetSymNameLookup(TInt aSymNameLkupEnabled) |
|
266 { |
|
267 if(aSymNameLkupEnabled) |
|
268 iHdr->iFlags |= KImageNmdExpData; |
|
269 else |
|
270 iHdr->iFlags &= ~KImageNmdExpData; |
|
271 } |
|
272 TBool E32ImageFile_ELF::IsNamedLookupEnabled() |
|
273 { |
|
274 return (iHdr->iFlags & KImageNmdExpData); |
|
275 } |
|
276 |
|
277 TBool E32ImageFile_ELF::SetUpLookupTable(ELFFile &aElfFile) |
|
278 // Symbol lookup by name is enabled. Create the symbol table with names |
|
279 // and their values. |
|
280 { |
|
281 if(!aElfFile.SetUpLookupTable() ) |
|
282 return FALSE; |
|
283 SetSymNameLookup(TRUE); |
|
284 return TRUE; |
|
285 } |
|
286 |
|
287 // Build the infrastructure for symbol lookup via name |
|
288 TInt E32ImageFile_ELF::DoSymbolLookupHeader(ELFFile &aElfFile, TInt aBaseOffset) |
|
289 { |
|
290 if(!IsNamedLookupEnabled()) |
|
291 return 0; |
|
292 |
|
293 aElfFile.SetLookupTblBase(aBaseOffset); |
|
294 return aElfFile.GetLookupTblSize(); |
|
295 } |
|
296 TUint E32ImageFile_ELF::CopyExportSymInfo(char *p, ELFFile &aElfFile) |
|
297 { |
|
298 iHdr->iCodeSize += aElfFile.GetLookupTblSize(); |
|
299 iHdr->iTextSize = iHdr->iCodeSize ; |
|
300 return aElfFile.GetSymLookupSection(p); |
|
301 } |