|
1 // Copyright (c) 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 // Classes that allow the editing and creation of Symbian ELF files |
|
15 // |
|
16 |
|
17 /** |
|
18 * @file selflib.cpp |
|
19 * @prototype |
|
20 */ |
|
21 |
|
22 #include <f32file.h> |
|
23 |
|
24 #include "selflib.h" |
|
25 #include "debuglogging.h" |
|
26 #include "symbianelfstringinfov2.h" |
|
27 #include "symbianelfstringinfo.h" |
|
28 |
|
29 /** |
|
30 * First stage construction |
|
31 * @return Pointer to new CSELFEditor object |
|
32 * @leave One of the System Wide Error Codes |
|
33 */ |
|
34 EXPORT_C CSELFEditor* CSELFEditor::NewL(const TDesC& aFilename) |
|
35 { |
|
36 LOG_ENTRY(); |
|
37 |
|
38 CSELFEditor* self = CSELFEditor::NewLC(aFilename); |
|
39 CleanupStack::Pop(); |
|
40 |
|
41 return self; |
|
42 } |
|
43 |
|
44 /** |
|
45 * First stage construction. Object is left upon cleanup stack |
|
46 * @return Pointer to new CSELFEditor object |
|
47 * @leave One of the System Wide Error Codes |
|
48 */ |
|
49 EXPORT_C CSELFEditor* CSELFEditor::NewLC(const TDesC& aFilename) |
|
50 { |
|
51 LOG_ENTRY(); |
|
52 |
|
53 CSELFEditor* self = new(ELeave)CSELFEditor(); |
|
54 CleanupStack::PushL(self); |
|
55 self->ConstructL(aFilename); |
|
56 |
|
57 return self; |
|
58 } |
|
59 |
|
60 /** |
|
61 * CSELFEditor Desctructor |
|
62 */ |
|
63 CSELFEditor::~CSELFEditor() |
|
64 { |
|
65 LOG_ENTRY(); |
|
66 |
|
67 delete iRawData; |
|
68 delete iStringTable; |
|
69 |
|
70 iELFFile.Close(); |
|
71 iFsSession.Close(); |
|
72 iNewSegments.Close(); |
|
73 iProgramHeaders.Close(); |
|
74 } |
|
75 |
|
76 /** |
|
77 * Second stage safe construction |
|
78 * @leave One of the System Wide Error Codes |
|
79 */ |
|
80 void CSELFEditor::ConstructL(const TDesC& aFilename) |
|
81 { |
|
82 LOG_ENTRY(); |
|
83 |
|
84 User::LeaveIfError(iFsSession.Connect()); |
|
85 User::LeaveIfError(iELFFile.Open(iFsSession, aFilename, EFileWrite)); |
|
86 |
|
87 TInt fileSize; |
|
88 User::LeaveIfError(iELFFile.Size(fileSize)); |
|
89 |
|
90 //Check its big enough to at least read the header |
|
91 if(fileSize < sizeof(Elf32_Ehdr)) |
|
92 { |
|
93 LOG_MSG("\tCSELFEditor::ConstructL --> File is not big enough to be an ELF file"); |
|
94 User::Leave(KErrCorrupt); |
|
95 } |
|
96 |
|
97 CacheELFHeaderL(); |
|
98 |
|
99 //Validate the ELF file |
|
100 if(!IsValidELFFile()) |
|
101 User::Leave(KErrCorrupt); |
|
102 |
|
103 if(!IsELFFileSupported()) |
|
104 User::Leave(KErrNotSupported); |
|
105 |
|
106 iRawData = new(ELeave) CDesC8ArrayFlat(1); |
|
107 |
|
108 CacheProgramHeadersL(); |
|
109 CacheStringTableL(); |
|
110 } |
|
111 |
|
112 /** |
|
113 * Caches ELF File internally in this object |
|
114 * @see GetELFHeader |
|
115 * @leave One of the system wide error codes |
|
116 */ |
|
117 void CSELFEditor::CacheELFHeaderL() |
|
118 { |
|
119 //Read the ELF header |
|
120 TUint fileLocation = 0; |
|
121 TPtr8 hdrDes((TUint8*)&iELFHeader, sizeof(Elf32_Ehdr)); |
|
122 User::LeaveIfError(iELFFile.Read(fileLocation, hdrDes)); |
|
123 } |
|
124 |
|
125 /** |
|
126 * CSELFEditor Constructor |
|
127 */ |
|
128 CSELFEditor::CSELFEditor() |
|
129 {} |
|
130 |
|
131 /** |
|
132 * This ELF library currently only supports a specific subset of the ELF standard. |
|
133 * This function makes sure the ELF file supplied is part of that subset. These are the things |
|
134 * we do not currently support: |
|
135 * 1. 64 Bit ELF |
|
136 * 2. ELFDATA2MSB File class (Big Endian) |
|
137 * 3. Any sections |
|
138 * 4. Any type other than ET_CORE |
|
139 * |
|
140 * @return TBool indicating if the file is OK to continue with |
|
141 */ |
|
142 TBool CSELFEditor::IsELFFileSupported() |
|
143 { |
|
144 LOG_ENTRY(); |
|
145 |
|
146 TBool supported = ETrue; |
|
147 if(iELFHeader.e_ident[EI_CLASS] != ELFCLASS32) |
|
148 { |
|
149 LOG_MSG("\tCSELFEditor::IsElfFileSupported() --> Non 32 bit files are not supported"); |
|
150 supported = EFalse; |
|
151 } |
|
152 |
|
153 if(iELFHeader.e_ident[EI_DATA] != ELFDATA2LSB) |
|
154 { |
|
155 LOG_MSG("\tCSELFEditor::IsElfFileSupported() --> Only support Little Endian"); |
|
156 supported = EFalse; |
|
157 } |
|
158 |
|
159 if(iELFHeader.e_type != ET_CORE) |
|
160 { |
|
161 LOG_MSG("\tCSELFEditor::IsElfFileSupported() --> Only support Core Files"); |
|
162 supported = EFalse; |
|
163 } |
|
164 |
|
165 if(iELFHeader.e_shoff != 0 || iELFHeader.e_shnum != 0) |
|
166 { |
|
167 LOG_MSG("\tCSELFEditor::IsElfFileSupported() --> Do not support Sections"); |
|
168 supported = EFalse; |
|
169 } |
|
170 |
|
171 return supported; |
|
172 } |
|
173 |
|
174 /** |
|
175 * Validates the ELF file by looking at the signature |
|
176 * @return Boolean indicating whether or not the file is valid ELF |
|
177 */ |
|
178 TBool CSELFEditor::IsValidELFFile() |
|
179 { |
|
180 LOG_ENTRY(); |
|
181 |
|
182 //Check signature |
|
183 return iELFHeader.e_ident[EI_MAG0] == ELFMAG0 && |
|
184 iELFHeader.e_ident[EI_MAG1] == ELFMAG1 && |
|
185 iELFHeader.e_ident[EI_MAG2] == ELFMAG2 && |
|
186 iELFHeader.e_ident[EI_MAG3] == ELFMAG3; |
|
187 } |
|
188 |
|
189 /** |
|
190 * Provides the ELF header of this file |
|
191 * @param aELFHeader Holds the ELF header after the call |
|
192 */ |
|
193 EXPORT_C void CSELFEditor::GetELFHeader(Elf32_Ehdr& aELFHeader) |
|
194 { |
|
195 LOG_ENTRY(); |
|
196 aELFHeader = iELFHeader; |
|
197 } |
|
198 |
|
199 /** |
|
200 * Caches the program headers from the file into this object |
|
201 * @leave One of the system wide codes |
|
202 */ |
|
203 void CSELFEditor::CacheProgramHeadersL() |
|
204 { |
|
205 LOG_ENTRY(); |
|
206 |
|
207 Elf32_Phdr progHeader; |
|
208 TPtr8 phdrPtr((TUint8*)&progHeader, sizeof(Elf32_Phdr)); |
|
209 |
|
210 TUint nextPh = iELFHeader.e_phoff; |
|
211 for(TUint i = 0; i < iELFHeader.e_phnum; i++) |
|
212 { |
|
213 User::LeaveIfError(iELFFile.Read(nextPh, phdrPtr)); |
|
214 iProgramHeaders.AppendL(progHeader); |
|
215 nextPh += sizeof(Elf32_Phdr); |
|
216 } |
|
217 } |
|
218 |
|
219 /** |
|
220 * Inserts variant specific data into the ELF file |
|
221 * @param aVarData The binary data to be inserted into the ELF file |
|
222 * @leave One of the system wide codes |
|
223 */ |
|
224 EXPORT_C void CSELFEditor::InsertVariantSpecificDataL(const TDesC8& aVarData) |
|
225 { |
|
226 LOG_ENTRY(); |
|
227 |
|
228 //Store the data in the raw data array, and record its position to associate with the new section |
|
229 iRawData->AppendL(aVarData); |
|
230 TUint position = iRawData->Count() - 1; |
|
231 |
|
232 //Now create the variant sepcific data dhdr and structure |
|
233 TSELFSegment newSegment; |
|
234 |
|
235 newSegment.iPhdr.p_type = PT_NOTE; |
|
236 newSegment.iPhdr.p_offset = 0; //Fill in when we write the file |
|
237 newSegment.iPhdr.p_vaddr = 0; |
|
238 newSegment.iPhdr.p_paddr = 0; |
|
239 newSegment.iPhdr.p_filesz =0; |
|
240 newSegment.iPhdr.p_memsz = 0; |
|
241 newSegment.iPhdr.p_flags = 0; |
|
242 newSegment.iPhdr.p_align = sizeof(TUint); |
|
243 |
|
244 newSegment.iDhdr.d_name = 0; //Fill in when we write the file (we need the string table) |
|
245 newSegment.iDhdr.d_type = ESYM_NOTE_VARIANT_DATA; |
|
246 newSegment.iDhdr.d_version = 0; //Fill in when we write the file (we need the string table) |
|
247 newSegment.iDhdr.d_elemnum = 1; |
|
248 newSegment.iDhdr.d_descrsz = sizeof(Sym32_variant_spec_data); |
|
249 |
|
250 Sym32_variant_spec_data* variantData = (Sym32_variant_spec_data*)(&newSegment.iType); |
|
251 variantData->es_data = position; //This data is in the iRawData until the write |
|
252 variantData->es_size = aVarData.Size(); |
|
253 |
|
254 iNewSegments.AppendL(newSegment); |
|
255 ++iELFHeader.e_phnum; |
|
256 } |
|
257 |
|
258 /** |
|
259 * Commits any changes made in the CSELFEditor to the ELF file |
|
260 * @leave One of the system wide codes |
|
261 */ |
|
262 EXPORT_C void CSELFEditor::WriteELFUpdatesL() |
|
263 { |
|
264 LOG_ENTRY(); |
|
265 |
|
266 //There may be nothing to do |
|
267 if(iNewSegments.Count() == 0) |
|
268 return; |
|
269 |
|
270 //Create tmp file |
|
271 TBuf<KMaxFileName> tmpFilename; |
|
272 RFile tmpFile; |
|
273 User::LeaveIfError(tmpFile.Temp(iFsSession, KTempFileLocation, tmpFilename, EFileWrite)); |
|
274 CleanupClosePushL(tmpFile); |
|
275 |
|
276 //Log file name |
|
277 TPtr8 smallName((TUint8*)tmpFilename.Ptr(), 2*tmpFilename.Length(), 2*tmpFilename.Length()); |
|
278 LOG_MSG2("\tWriteELFUpdatesL() --> Writing new temporary updates to [%S]", &smallName); |
|
279 |
|
280 TUint numberofPhdrs = 0; |
|
281 |
|
282 //Leave space for elf header plus program header table at start |
|
283 TUint spaceToLeave =+ sizeof(Elf32_Ehdr) + (iNewSegments.Count() + iProgramHeaders.Count() ) * sizeof(Elf32_Phdr); |
|
284 PutEmptySpaceAtEndOfFileL(tmpFile, spaceToLeave); |
|
285 |
|
286 TUint phdrLoc = sizeof(Elf32_Ehdr); //phdr table starts just after ELF header |
|
287 TUint dataLoc = spaceToLeave; |
|
288 |
|
289 LOG_MSG("WriteELFUpdatesL --> Copying existing program headers to the tmp file"); |
|
290 |
|
291 //Store new program headers as we go |
|
292 RArray<Elf32_Phdr> newProgramHeaders; |
|
293 |
|
294 { |
|
295 Elf32_Phdr phdr; |
|
296 TPtr8 phdrPtr((TUint8*)&phdr, sizeof(Elf32_Phdr), sizeof(Elf32_Phdr)); |
|
297 |
|
298 for(TUint i = 0; i < iProgramHeaders.Count(); i++) |
|
299 { |
|
300 phdr = iProgramHeaders[i]; |
|
301 |
|
302 //Now we put the neccesary data after the phdr table |
|
303 if(phdr.p_type == PT_LOAD && phdr.p_filesz != 0 && phdr.p_offset != 0) |
|
304 { |
|
305 phdr.p_offset = CopyFromELFFileL(phdr.p_offset, phdr.p_filesz, tmpFile, dataLoc); |
|
306 dataLoc += phdr.p_filesz; |
|
307 } |
|
308 else if(phdr.p_type == PT_NOTE) |
|
309 { |
|
310 //Read the symbian descriptor |
|
311 READ_STRUCTL(Sym32_dhdr, symd, iELFFile, phdr.p_offset); |
|
312 |
|
313 //TODO: The fact that we need this *MAY* indicate flaws in SELF format. It would be nice |
|
314 //to be able to copy a bit that was completely described by the dhdr |
|
315 if(symd.d_type == ESYM_NOTE_REG) |
|
316 { |
|
317 //registers cant just be blindly copied as they contain offsets that need updating |
|
318 TUint sizeWritten = 0; |
|
319 phdr.p_offset = CopyRegistersL(tmpFile, phdr.p_offset, dataLoc, sizeWritten); |
|
320 dataLoc += sizeWritten; |
|
321 } |
|
322 else if(symd.d_type == ESYM_NOTE_VARIANT_DATA) |
|
323 { |
|
324 //Variant data cant be blindly copied either as they have offsets too |
|
325 TUint sizeWritten = 0; |
|
326 phdr.p_offset = CopyVariantDataL(tmpFile, phdr.p_offset, dataLoc, sizeWritten); |
|
327 dataLoc += sizeWritten; |
|
328 } |
|
329 //special case - needs updating so do after everything else |
|
330 else if(symd.d_type == ESYM_NOTE_STR) |
|
331 { |
|
332 continue; |
|
333 } |
|
334 else |
|
335 { |
|
336 TUint sizetoCopy = sizeof(Sym32_dhdr) + symd.d_descrsz * symd.d_elemnum; |
|
337 phdr.p_offset = CopyFromELFFileL(phdr.p_offset, sizetoCopy, tmpFile, dataLoc); |
|
338 dataLoc += sizetoCopy; |
|
339 } |
|
340 |
|
341 } |
|
342 |
|
343 //Write the updated program header |
|
344 User::LeaveIfError(tmpFile.Write(phdrLoc, phdrPtr)); |
|
345 phdrLoc += sizeof(Elf32_Phdr); |
|
346 newProgramHeaders.AppendL(phdr); |
|
347 ++numberofPhdrs; |
|
348 } |
|
349 LOG_MSG2("WriteELFUpdatesL --> Copied [%d] existing program headers (minus string table)", numberofPhdrs); |
|
350 } |
|
351 |
|
352 //Now we add the new segments |
|
353 |
|
354 //This is for the string table |
|
355 TBuf8<KMaxFileName> varDataBuf; |
|
356 varDataBuf.Format(_L8("CORE.SYMBIAN.VARDATA")); |
|
357 TUint versionIndex = iStringTable->GetIndex(KSymbianElfCoreDumpVersionV2); |
|
358 |
|
359 for(TUint i = 0; i < iNewSegments.Count(); i++) |
|
360 { |
|
361 TSELFSegment segment = iNewSegments[i]; |
|
362 |
|
363 //Update the program header and the d_hdr |
|
364 segment.iPhdr.p_offset = dataLoc; |
|
365 |
|
366 |
|
367 TInt index = iStringTable->AddStringL(varDataBuf); |
|
368 segment.iDhdr.d_name = (index == KErrNotFound) ? ESYM_STR_UNDEF : index; |
|
369 segment.iDhdr.d_version = versionIndex; |
|
370 |
|
371 Sym32_variant_spec_data* variantData = (Sym32_variant_spec_data*)(&segment.iType); |
|
372 TUint dataIndex = variantData->es_data; |
|
373 variantData->es_data = dataLoc + sizeof(Sym32_variant_spec_data) + sizeof(Sym32_dhdr); |
|
374 |
|
375 //Write the phdr |
|
376 TPtr8 nphdrPtr((TUint8*)&segment.iPhdr, sizeof(Elf32_Phdr), sizeof(Elf32_Phdr)); |
|
377 User::LeaveIfError(tmpFile.Write(phdrLoc, nphdrPtr)); |
|
378 newProgramHeaders.AppendL(segment.iPhdr); |
|
379 phdrLoc += sizeof(Elf32_Phdr); |
|
380 ++numberofPhdrs; |
|
381 |
|
382 //Write the dhdr |
|
383 TPtr8 ndhdrPtr((TUint8*)&segment.iDhdr, sizeof(Sym32_dhdr), sizeof(Sym32_dhdr)); |
|
384 User::LeaveIfError(tmpFile.Write(dataLoc, ndhdrPtr)); |
|
385 dataLoc += sizeof(Sym32_dhdr); |
|
386 |
|
387 //Write the var struct |
|
388 TPtr8 nvarHdr((TUint8*)&segment.iType, sizeof(Sym32_variant_spec_data), sizeof(Sym32_variant_spec_data)); |
|
389 User::LeaveIfError(tmpFile.Write(dataLoc, nvarHdr)); |
|
390 dataLoc += sizeof(Sym32_variant_spec_data); |
|
391 |
|
392 //Write the data |
|
393 User::LeaveIfError(tmpFile.Write(dataLoc, (*iRawData)[dataIndex])); |
|
394 dataLoc += variantData->es_size; |
|
395 } |
|
396 |
|
397 //Write the string info |
|
398 Elf32_Phdr sphdr; |
|
399 TPtr8 sphdrPtr((TUint8*)&sphdr, sizeof(Elf32_Phdr), sizeof(Elf32_Phdr)); |
|
400 |
|
401 sphdr.p_type = PT_NOTE; |
|
402 sphdr.p_offset = WriteStringInfoL(tmpFile, dataLoc); |
|
403 sphdr.p_vaddr = 0; |
|
404 sphdr.p_paddr = 0; |
|
405 sphdr.p_filesz = 0; |
|
406 sphdr.p_memsz = 0; |
|
407 sphdr.p_flags = 0; |
|
408 sphdr.p_align = 4; |
|
409 |
|
410 User::LeaveIfError(tmpFile.Write(phdrLoc, sphdrPtr)); |
|
411 newProgramHeaders.Append(sphdr); |
|
412 phdrLoc += sizeof(Elf32_Phdr); |
|
413 ++numberofPhdrs; |
|
414 |
|
415 //Last thing, is to finally update the ELF header and write it |
|
416 iELFHeader.e_phoff = sizeof(Elf32_Ehdr); |
|
417 iELFHeader.e_phnum = numberofPhdrs; |
|
418 |
|
419 LOG_MSG("\tWriting final ELF Header"); |
|
420 TPtr8 hdrPtr((TUint8*)&iELFHeader, sizeof(Elf32_Ehdr), sizeof(Elf32_Ehdr)); |
|
421 User::LeaveIfError(tmpFile.Write(0, hdrPtr)); |
|
422 |
|
423 tmpFile.Flush(); |
|
424 CleanupStack::PopAndDestroy(&tmpFile); |
|
425 |
|
426 TBuf<KMaxFileName> origFilename; |
|
427 iELFFile.FullName(origFilename); |
|
428 iELFFile.Close(); |
|
429 |
|
430 SwapFilesL(tmpFilename, origFilename); |
|
431 |
|
432 //Open the file again for further use and reset data structs |
|
433 User::LeaveIfError(iELFFile.Open(iFsSession, origFilename, EFileWrite)); |
|
434 |
|
435 iNewSegments.Reset(); |
|
436 iProgramHeaders.Close(); |
|
437 iProgramHeaders = newProgramHeaders; //Update with latest p hdrs |
|
438 } |
|
439 |
|
440 /** |
|
441 * Writes the string info at specified offset |
|
442 * This writes the Sym32_dhdr and the string info |
|
443 * @param aFile File to write to |
|
444 * @param aOffset Position in file to write to. This is updated and finishes at the next free point to |
|
445 * write to in this file |
|
446 * @leave One of the system wide codes |
|
447 * @return Offset in the file where this was written to (the initial value of aOffset) |
|
448 */ |
|
449 TUint CSELFEditor::WriteStringInfoL(RFile aFile, TUint& aOffset) |
|
450 { |
|
451 LOG_ENTRY(); |
|
452 |
|
453 TUint writeStart = aOffset; |
|
454 |
|
455 Sym32_dhdr dhdr; |
|
456 TPtr8 dhdrPtr((TUint8*)&dhdr, sizeof(Sym32_dhdr), sizeof(Sym32_dhdr)); |
|
457 |
|
458 TInt index = iStringTable->GetIndex(KStr); |
|
459 dhdr.d_name = (index == KErrNotFound) ? ESYM_STR_UNDEF : index; |
|
460 dhdr.d_descrsz = iStringTable->GetSize(); |
|
461 dhdr.d_type = ESYM_NOTE_STR; |
|
462 dhdr.d_version = iStringTable->GetIndex(KSymbianElfCoreDumpVersionV2); |
|
463 dhdr.d_elemnum = 1; |
|
464 |
|
465 //Write the dhdr |
|
466 User::LeaveIfError(aFile.Write(aOffset, dhdrPtr)); |
|
467 aOffset += sizeof(Sym32_dhdr); |
|
468 |
|
469 //Write the string info |
|
470 TText8* buf = iStringTable->GetAllStrings(); |
|
471 TUint size = iStringTable->GetSize(); |
|
472 |
|
473 TPtr8 data((TUint8*)buf, size, size); |
|
474 User::LeaveIfError(aFile.Write(aOffset, data)); |
|
475 aOffset += size; |
|
476 |
|
477 return writeStart; |
|
478 } |
|
479 |
|
480 /** |
|
481 * Copies the registers to aFile sensibly, updating the offsets accordingly |
|
482 * @param aFile Destination file |
|
483 * @param aSrcRead Place in src file where d_hdr starts |
|
484 * @param aDestWrite Destination to write to |
|
485 * @leave One of the system wide codes |
|
486 */ |
|
487 TUint CSELFEditor::CopyRegistersL(RFile aFile, TUint aSrcRead, TUint aDestWrite, TUint& aSizeWritten) |
|
488 { |
|
489 LOG_ENTRY(); |
|
490 |
|
491 aSizeWritten = 0; |
|
492 TUint srcpos = aSrcRead; |
|
493 TUint destpos = aDestWrite; |
|
494 |
|
495 //Write the dhdr, it wont change |
|
496 READ_STRUCTL(Sym32_dhdr, dhdr, iELFFile, srcpos); |
|
497 CopyFromELFFileL(srcpos, sizeof(Sym32_dhdr), aFile, destpos); |
|
498 srcpos += sizeof(Sym32_dhdr); |
|
499 destpos += sizeof(Sym32_dhdr); |
|
500 |
|
501 //And the reginfod struct |
|
502 READ_STRUCTL(Sym32_reginfod, reginfo, iELFFile, srcpos); |
|
503 CopyFromELFFileL(srcpos, sizeof(Sym32_reginfod), aFile, destpos); |
|
504 srcpos += sizeof(Sym32_reginfod); |
|
505 destpos += sizeof(Sym32_reginfod); |
|
506 |
|
507 RBuf8 regVals; |
|
508 regVals.CreateL(reginfo.rid_num_registers * sizeof(TUint64)); |
|
509 regVals.CleanupClosePushL(); |
|
510 |
|
511 //Now we need to go through the individual register values. They are offset to somewhere and |
|
512 //we need to figure out where we will be putting them first |
|
513 TUint regoffset = destpos + (reginfo.rid_num_registers * sizeof(Sym32_regdatad) ); |
|
514 for(TUint i = 0; i < reginfo.rid_num_registers; i++) |
|
515 { |
|
516 READ_STRUCTL(Sym32_regdatad, regdata, iELFFile, srcpos); |
|
517 srcpos += sizeof(Sym32_regdatad); |
|
518 |
|
519 //update the offset |
|
520 TUint srcOffset = regdata.rd_data; |
|
521 regdata.rd_data = regoffset; |
|
522 regoffset += sizeof(TUint64); |
|
523 |
|
524 //Write it to the file |
|
525 TPtr8 dataPtr((TUint8*)®data, sizeof(Sym32_regdatad), sizeof(Sym32_regdatad)); |
|
526 User::LeaveIfError(aFile.Write(destpos, dataPtr)); |
|
527 destpos += sizeof(Sym32_regdatad); |
|
528 |
|
529 //Read the appropriate value |
|
530 TUint32 regValue = 0; |
|
531 TPtr8 regValuePtr((TUint8*)®Value, sizeof(TUint64), sizeof(TUint64)); |
|
532 |
|
533 switch(reginfo.rid_repre) |
|
534 { |
|
535 case ESYM_REG_8: |
|
536 User::LeaveIfError(iELFFile.Read(srcOffset, regValuePtr, sizeof(TUint8))); |
|
537 break; |
|
538 case ESYM_REG_16: |
|
539 User::LeaveIfError(iELFFile.Read(srcOffset, regValuePtr, sizeof(TUint16))); |
|
540 break; |
|
541 case ESYM_REG_32: |
|
542 User::LeaveIfError(iELFFile.Read(srcOffset, regValuePtr, sizeof(TUint32))); |
|
543 break; |
|
544 case ESYM_REG_64: |
|
545 User::LeaveIfError(iELFFile.Read(srcOffset, regValuePtr, sizeof(TUint64))); |
|
546 break; |
|
547 default: |
|
548 regValue = 0; |
|
549 break; |
|
550 } |
|
551 |
|
552 regValuePtr.SetLength(sizeof(TUint64)); |
|
553 regVals.Append(regValuePtr); |
|
554 } |
|
555 |
|
556 //Now write the values |
|
557 User::LeaveIfError(aFile.Write(destpos, regVals)); |
|
558 destpos += regVals.Size(); |
|
559 |
|
560 CleanupStack::PopAndDestroy(®Vals); |
|
561 |
|
562 aSizeWritten = destpos - aDestWrite; |
|
563 return aDestWrite; |
|
564 } |
|
565 |
|
566 /** |
|
567 * Copies the variant data to aFile sensibly, updating the offsets accordingly |
|
568 * @param aFile Destination file |
|
569 * @param aSrcRead Place in src file where d_hdr starts |
|
570 * @param aDestWrite Destination to write to |
|
571 * @leave One of the system wide codes |
|
572 */ |
|
573 TUint CSELFEditor::CopyVariantDataL(RFile aFile, TUint aSrcRead, TUint aDestWrite, TUint& aSizeWritten) |
|
574 { |
|
575 LOG_ENTRY(); |
|
576 |
|
577 aSizeWritten = 0; |
|
578 TUint srcpos = aSrcRead; |
|
579 TUint destpos = aDestWrite; |
|
580 |
|
581 //Write the dhdr, it wont change |
|
582 READ_STRUCTL(Sym32_dhdr, dhdr, iELFFile, srcpos); |
|
583 CopyFromELFFileL(srcpos, sizeof(Sym32_dhdr), aFile, destpos); |
|
584 srcpos += sizeof(Sym32_dhdr); |
|
585 destpos += sizeof(Sym32_dhdr); |
|
586 |
|
587 //And the var data struct |
|
588 READ_STRUCTL(Sym32_variant_spec_data, varData, iELFFile, srcpos); |
|
589 varData.es_data = destpos + sizeof(Sym32_variant_spec_data); |
|
590 |
|
591 TPtr8 varDataPtr((TUint8*)&varData, sizeof(Sym32_variant_spec_data), sizeof(Sym32_variant_spec_data)); |
|
592 User::LeaveIfError(aFile.Write(destpos, varDataPtr)); |
|
593 srcpos += sizeof(Sym32_variant_spec_data); |
|
594 destpos += sizeof(Sym32_variant_spec_data); |
|
595 |
|
596 //And the data |
|
597 CopyFromELFFileL(srcpos, varData.es_size, aFile, destpos); |
|
598 srcpos += varData.es_size; |
|
599 destpos += varData.es_size; |
|
600 |
|
601 aSizeWritten = destpos - aDestWrite; |
|
602 return aDestWrite; |
|
603 } |
|
604 |
|
605 /** |
|
606 * Copies a part of the ELF file into a destination file |
|
607 * @param aStartPoint Point in file to start copying |
|
608 * @param aSize Amount to copy |
|
609 * @param aDestinationFile Destination file to copy to |
|
610 * @param aDestWrite Position in destination to write to |
|
611 * @return Place in file where this has been written |
|
612 * @leave One of the System wide codes |
|
613 */ |
|
614 TUint CSELFEditor::CopyFromELFFileL(TUint aStartPoint, TUint aSize, RFile aDestinationFile, TUint aDestWrite) |
|
615 { |
|
616 TUint readpos = aStartPoint; |
|
617 TUint endpoint = aStartPoint + aSize; |
|
618 TUint destpos = aDestWrite; |
|
619 |
|
620 //Use free memory/10 for our buffering |
|
621 TInt block = 0; |
|
622 TInt freemem = User::Available(block); |
|
623 TInt maxfilecopysize = freemem/10; |
|
624 |
|
625 RBuf8 copybuf; |
|
626 copybuf.CreateL(maxfilecopysize); |
|
627 copybuf.CleanupClosePushL(); |
|
628 |
|
629 while(readpos < endpoint) |
|
630 { |
|
631 TUint readsize = maxfilecopysize; |
|
632 if(readpos + readsize > endpoint) |
|
633 readsize = endpoint - readpos; |
|
634 |
|
635 if(readsize != copybuf.MaxLength()) |
|
636 copybuf.ReAllocL(readsize); |
|
637 |
|
638 User::LeaveIfError(iELFFile.Read(readpos, copybuf, readsize)); |
|
639 User::LeaveIfError(aDestinationFile.Write(destpos, copybuf)); |
|
640 |
|
641 copybuf.Zero(); |
|
642 |
|
643 destpos += readsize; |
|
644 readpos += readsize; |
|
645 } |
|
646 |
|
647 CleanupStack::PopAndDestroy(©buf); |
|
648 |
|
649 return aDestWrite; |
|
650 } |
|
651 |
|
652 /** |
|
653 * Caches the string table in source ELF file into our string info table object |
|
654 * @leaves One of the system wide codes |
|
655 */ |
|
656 void CSELFEditor::CacheStringTableL() |
|
657 { |
|
658 LOG_ENTRY(); |
|
659 |
|
660 for(TUint i = 0; i < iProgramHeaders.Count(); i++) |
|
661 { |
|
662 Elf32_Phdr phdr = iProgramHeaders[i]; |
|
663 |
|
664 READ_STRUCTL(Sym32_dhdr, dhdr, iELFFile, phdr.p_offset); |
|
665 if(dhdr.d_type == ESYM_NOTE_STR) |
|
666 { |
|
667 iStringTableDhdr = dhdr; |
|
668 |
|
669 RBuf8 stringData; |
|
670 stringData.CreateL(dhdr.d_descrsz); |
|
671 stringData.CleanupClosePushL(); |
|
672 |
|
673 User::LeaveIfError(iELFFile.Read(phdr.p_offset + sizeof(Sym32_dhdr), stringData)); |
|
674 iStringTable = CStringInfoTableV2::NewL(stringData); |
|
675 |
|
676 CleanupStack::PopAndDestroy(&stringData); |
|
677 return; |
|
678 } |
|
679 } |
|
680 } |
|
681 |
|
682 /** |
|
683 * Utility function to leave space in the file |
|
684 * @param aFile |
|
685 * @param aSize |
|
686 */ |
|
687 void CSELFEditor::PutEmptySpaceAtEndOfFileL(RFile aFile, TUint aSize) |
|
688 { |
|
689 LOG_ENTRY(); |
|
690 |
|
691 RBuf8 empty; |
|
692 empty.CreateL(aSize); |
|
693 empty.CleanupClosePushL(); |
|
694 empty.SetLength(aSize); |
|
695 |
|
696 LOG_MSG2("\tPutEmptySpaceAtEndOfFileL --> Leaving [0x%X] bytes", aSize); |
|
697 User::LeaveIfError(aFile.Write(empty)); |
|
698 |
|
699 CleanupStack::PopAndDestroy(&empty); |
|
700 } |
|
701 |
|
702 /** |
|
703 * Swaps 2 files and deletes the original destination |
|
704 * @leave One of the system wide codes |
|
705 */ |
|
706 void CSELFEditor::SwapFilesL(const TDesC& aSrc, const TDesC& aDest) |
|
707 { |
|
708 LOG_ENTRY(); |
|
709 |
|
710 //1. Back up the destination file in case anything fails |
|
711 TBuf<KMaxFileName> backupName; |
|
712 backupName.Copy(aDest); |
|
713 backupName.Append(_L(".bak")); |
|
714 |
|
715 CFileMan* fmanager = CFileMan::NewL(iFsSession); |
|
716 CleanupStack::PushL(fmanager); |
|
717 |
|
718 User::LeaveIfError(fmanager->Rename(aDest, backupName)); |
|
719 |
|
720 //2. Rename the src file to the dest file |
|
721 TInt err = fmanager->Move(aSrc, aDest); |
|
722 if(KErrNone != err) |
|
723 { |
|
724 //rename failed so restore original file |
|
725 TPtr8 dest8((TUint8*)aDest.Ptr(), 2*aDest.Length(), 2*aDest.Length()); |
|
726 RDebug::Printf("\nFailed to move the tmp file so restoring original file [%S]", &dest8); |
|
727 User::LeaveIfError(fmanager->Rename(backupName, aDest)); |
|
728 User::Leave(err); |
|
729 } |
|
730 |
|
731 //3. Delete the backup file file |
|
732 User::LeaveIfError(fmanager->Delete(backupName)); |
|
733 CleanupStack::PopAndDestroy(fmanager); |
|
734 } |