dbgsrv/coredumpserver/plugins/formatters/symbianelf/selflib/selflib.cpp
changeset 0 c6b0df440bee
equal deleted inserted replaced
-1:000000000000 0:c6b0df440bee
       
     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*)&regdata, 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*)&regValue, 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(&regVals);
       
   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(&copybuf);
       
   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 	}