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