From 0bc9421b147f6f54d6fde72e320466d2db61ae8c Mon Sep 17 00:00:00 2001 From: jljusten Date: Sun, 26 Jun 2011 18:58:10 +0000 Subject: [PATCH] InOsEmuPkg/Unix: Auto-load symbols files in gdb Images that can't be loaded with dlopen are added to SecMain.gdb. Whenever gdb stops, the hook-stop macro will automatically load the symbol files. Signed-off-by: jljusten git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11888 6f19259b-4bc3-4df7-8a09-765794883524 --- InOsEmuPkg/Unix/GdbRun | 37 +++++ InOsEmuPkg/Unix/Sec/SecMain.c | 288 ++++++++++++++++++---------------- 2 files changed, 191 insertions(+), 134 deletions(-) diff --git a/InOsEmuPkg/Unix/GdbRun b/InOsEmuPkg/Unix/GdbRun index cf4ca7fe5a..c374cb8ca5 100644 --- a/InOsEmuPkg/Unix/GdbRun +++ b/InOsEmuPkg/Unix/GdbRun @@ -27,6 +27,43 @@ set $_exitcode = 42 define hook-stop if $_exitcode != 42 quit + else + source SecMain.gdb + end +end + +# +# We keep track of the number of symbol files we have loaded via gdb +# scripts in the $SymbolFilesAdded variable +# +set $SymbolFileChangesCount = 0 + +# +# This macro adds a symbols file for gdb +# +# @param $arg0 - Symbol file changes number +# @param $arg1 - Symbol file name +# @param $arg2 - Image address +# +define AddFirmwareSymbolFile + if $SymbolFileChangesCount < $arg0 + add-symbol-file $arg1 $arg2 + set $SymbolFileChangesCount = $arg0 + end +end + +# +# This macro removes a symbols file for gdb +# +# @param $arg0 - Symbol file changes number +# @param $arg1 - Symbol file name +# +define RemoveFirmwareSymbolFile + if $SymbolFileChangesCount < $arg0 + # + # Currently there is not a method to remove a single symbol file + # + set $SymbolFileChangesCount = $arg0 end end diff --git a/InOsEmuPkg/Unix/Sec/SecMain.c b/InOsEmuPkg/Unix/Sec/SecMain.c index bcf4104b1b..61847b5348 100644 --- a/InOsEmuPkg/Unix/Sec/SecMain.c +++ b/InOsEmuPkg/Unix/Sec/SecMain.c @@ -16,7 +16,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #ifdef __APPLE__ #define MAP_ANONYMOUS MAP_ANON -char *gGdbWorkingFileName = NULL; #endif @@ -30,7 +29,8 @@ EMU_THUNK_PPI mSecEmuThunkPpi = { GasketSecEmuThunkAddress }; - +char *gGdbWorkingFileName = NULL; +UINTN mScriptSymbolChangesCount = 0; // @@ -95,6 +95,7 @@ main ( CHAR16 *MemorySizeStr; CHAR16 *FirmwareVolumesStr; UINTN *StackPointer; + FILE *GdbTempFile; setbuf (stdout, 0); setbuf (stderr, 0); @@ -128,19 +129,22 @@ main ( gPpiList = GetThunkPpiList (); - -#ifdef __APPLE__ // - // We can't use dlopen on OS X, so we need a scheme to get symboles into gdb - // We need to create a temp file that contains gdb commands so we can load - // symbols when we load every PE/COFF image. + // If dlopen doesn't work, then we build a gdb script to allow the + // symbols to be loaded. // Index = strlen (*Argv); gGdbWorkingFileName = AllocatePool (Index + strlen(".gdb") + 1); strcpy (gGdbWorkingFileName, *Argv); strcat (gGdbWorkingFileName, ".gdb"); -#endif + // + // Empty out the gdb symbols script file. + // + GdbTempFile = fopen (gGdbWorkingFileName, "w"); + if (GdbTempFile != NULL) { + fclose (GdbTempFile); + } // // Allocate space for gSystemMemory Array @@ -1050,89 +1054,25 @@ PrintLoadAddress ( } -VOID -EFIAPI -SecPeCoffRelocateImageExtraAction ( +/** + Loads the image using dlopen so symbols will be automatically + loaded by gdb. + + @param ImageContext The PE/COFF image context + + @retval TRUE - The image was successfully loaded + @retval FALSE - The image was successfully loaded + +**/ +BOOLEAN +DlLoadImage ( IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext ) { #ifdef __APPLE__ - BOOLEAN EnabledOnEntry; - - // - // Make sure writting of the file is an atomic operation - // - if (SecInterruptEanbled ()) { - SecDisableInterrupt (); - EnabledOnEntry = TRUE; - } else { - EnabledOnEntry = FALSE; - } - - PrintLoadAddress (ImageContext); - - // - // In mach-o (OS X executable) dlopen() can only load files in the MH_DYLIB of MH_BUNDLE format. - // To convert to PE/COFF we need to construct a mach-o with the MH_PRELOAD format. We create - // .dSYM files for the PE/COFF images that can be used by gdb for source level debugging. - // - FILE *GdbTempFile; - - // - // In the Mach-O to PE/COFF conversion the size of the PE/COFF headers is not accounted for. - // Thus we need to skip over the PE/COFF header when giving load addresses for our symbol table. - // - if (ImageContext->PdbPointer != NULL && !IsPdbFile (ImageContext->PdbPointer)) { - // - // Now we have a database of the images that are currently loaded - // - - // - // 'symbol-file' will clear out currnet symbol mappings in gdb. - // you can do a 'add-symbol-file filename address' for every image we loaded to get source - // level debug in gdb. Note Sec, being a true application will work differently. - // - // We add the PE/COFF header size into the image as the mach-O does not have a header in - // loaded into system memory. - // - // This gives us a data base of gdb commands and after something is unloaded that entry will be - // removed. We don't yet have the scheme of how to comunicate with gdb, but we have the - // data base of info ready to roll. - // - // We could use qXfer:libraries:read, but OS X GDB does not currently support it. - // - // // ImageContext->PdbPointer - // // ImageContext->ImageAddress + ImageContext->SizeOfHeaders - // - // - // - - // - // Write the file we need for the gdb script - // - GdbTempFile = fopen (gGdbWorkingFileName, "w"); - if (GdbTempFile != NULL) { - fprintf (GdbTempFile, "add-symbol-file %s 0x%08lx\n", ImageContext->PdbPointer, (long unsigned int)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders)); - fclose (GdbTempFile); - - // - // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to set a breakpoint. - // Hey what can you say scripting in gdb is not that great.... - // - SecGdbScriptBreak (); - } else { - ASSERT (FALSE); - } - - AddHandle (ImageContext, ImageContext->PdbPointer); - if (EnabledOnEntry) { - SecEnableInterrupt (); - } - - - } + return FALSE; #else @@ -1140,11 +1080,11 @@ SecPeCoffRelocateImageExtraAction ( void *Entry = NULL; if (ImageContext->PdbPointer == NULL) { - return; + return FALSE; } if (!IsPdbFile (ImageContext->PdbPointer)) { - return; + return FALSE; } fprintf ( @@ -1166,75 +1106,155 @@ SecPeCoffRelocateImageExtraAction ( if (Entry != NULL) { ImageContext->EntryPoint = (UINTN)Entry; printf ("Change %s Entrypoint to :0x%08lx\n", ImageContext->PdbPointer, (unsigned long)Entry); + return TRUE; + } else { + return FALSE; } - SecUnixLoaderBreak (); - #endif +} + + +/** + Adds the image to a gdb script so it's symbols can be loaded. + The AddFirmwareSymbolFile helper macro is used. + + @param ImageContext The PE/COFF image context + +**/ +VOID +GdbScriptAddImage ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + BOOLEAN InterruptsWereEnabled; - return; + // + // Disable interrupts to make sure writing of the .gdb file + // is an atomic operation. + // + if (SecInterruptEanbled ()) { + SecDisableInterrupt (); + InterruptsWereEnabled = TRUE; + } else { + InterruptsWereEnabled = FALSE; + } + + PrintLoadAddress (ImageContext); + + if (ImageContext->PdbPointer != NULL && !IsPdbFile (ImageContext->PdbPointer)) { + FILE *GdbTempFile; + GdbTempFile = fopen (gGdbWorkingFileName, "a"); + if (GdbTempFile != NULL) { + long unsigned int SymbolsAddr = (long unsigned int)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders); + mScriptSymbolChangesCount++; + fprintf ( + GdbTempFile, + "AddFirmwareSymbolFile 0x%x %s 0x%08lx\n", + mScriptSymbolChangesCount, + ImageContext->PdbPointer, + SymbolsAddr + ); + fclose (GdbTempFile); + } else { + ASSERT (FALSE); + } + + AddHandle (ImageContext, ImageContext->PdbPointer); + + if (InterruptsWereEnabled) { + SecEnableInterrupt (); + } + + } } VOID EFIAPI -SecPeCoffUnloadImageExtraAction ( - IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext +SecPeCoffRelocateImageExtraAction ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext ) { - VOID *Handle; + if (!DlLoadImage (ImageContext)) { + GdbScriptAddImage (ImageContext); + } +} - Handle = RemoveHandle (ImageContext); -#ifdef __APPLE__ +/** + Adds the image to a gdb script so it's symbols can be unloaded. + The RemoveFirmwareSymbolFile helper macro is used. + + @param ImageContext The PE/COFF image context + +**/ +VOID +GdbScriptRemoveImage ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ FILE *GdbTempFile; - BOOLEAN EnabledOnEntry; + BOOLEAN InterruptsWereEnabled; - if (Handle != NULL) { - // - // Need to skip .PDB files created from VC++ - // - if (!IsPdbFile (ImageContext->PdbPointer)) { - if (SecInterruptEanbled ()) { - SecDisableInterrupt (); - EnabledOnEntry = TRUE; - } else { - EnabledOnEntry = FALSE; - } - - // - // Write the file we need for the gdb script - // - GdbTempFile = fopen (gGdbWorkingFileName, "w"); - if (GdbTempFile != NULL) { - fprintf (GdbTempFile, "remove-symbol-file %s\n", ImageContext->PdbPointer); - fclose (GdbTempFile); - - // - // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to set a breakpoint. - // Hey what can you say scripting in gdb is not that great.... - // - SecGdbScriptBreak (); - } else { - ASSERT (FALSE); - } - - if (EnabledOnEntry) { - SecEnableInterrupt (); - } - } + // + // Need to skip .PDB files created from VC++ + // + if (IsPdbFile (ImageContext->PdbPointer)) { + return; + } + + if (SecInterruptEanbled ()) { + SecDisableInterrupt (); + InterruptsWereEnabled = TRUE; + } else { + InterruptsWereEnabled = FALSE; } -#else // - // Don't want to confuse gdb with symbols for something that got unloaded + // Write the file we need for the gdb script // - if (Handle != NULL) { - dlclose (Handle); + GdbTempFile = fopen (gGdbWorkingFileName, "a"); + if (GdbTempFile != NULL) { + mScriptSymbolChangesCount++; + fprintf ( + GdbTempFile, + "RemoveFirmwareSymbolFile 0x%x %s\n", + mScriptSymbolChangesCount, + ImageContext->PdbPointer + ); + fclose (GdbTempFile); + } else { + ASSERT (FALSE); + } + + if (InterruptsWereEnabled) { + SecEnableInterrupt (); } +} + +VOID +EFIAPI +SecPeCoffUnloadImageExtraAction ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + VOID *Handle; + + // + // Check to see if the image symbols were loaded with gdb script, or dlopen + // + Handle = RemoveHandle (ImageContext); + + if (Handle == NULL) { +#ifndef __APPLE__ + dlclose (Handle); #endif - return; + return; + } + + GdbScriptRemoveImage (ImageContext); } -- 2.39.2