mirror of https://github.com/acidanthera/audk.git
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
This commit is contained in:
parent
8e4b3d32a8
commit
0bc9421b14
|
@ -27,6 +27,43 @@ set $_exitcode = 42
|
||||||
define hook-stop
|
define hook-stop
|
||||||
if $_exitcode != 42
|
if $_exitcode != 42
|
||||||
quit
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#define MAP_ANONYMOUS MAP_ANON
|
#define MAP_ANONYMOUS MAP_ANON
|
||||||
char *gGdbWorkingFileName = NULL;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,7 +29,8 @@ EMU_THUNK_PPI mSecEmuThunkPpi = {
|
||||||
GasketSecEmuThunkAddress
|
GasketSecEmuThunkAddress
|
||||||
};
|
};
|
||||||
|
|
||||||
|
char *gGdbWorkingFileName = NULL;
|
||||||
|
UINTN mScriptSymbolChangesCount = 0;
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -95,6 +95,7 @@ main (
|
||||||
CHAR16 *MemorySizeStr;
|
CHAR16 *MemorySizeStr;
|
||||||
CHAR16 *FirmwareVolumesStr;
|
CHAR16 *FirmwareVolumesStr;
|
||||||
UINTN *StackPointer;
|
UINTN *StackPointer;
|
||||||
|
FILE *GdbTempFile;
|
||||||
|
|
||||||
setbuf (stdout, 0);
|
setbuf (stdout, 0);
|
||||||
setbuf (stderr, 0);
|
setbuf (stderr, 0);
|
||||||
|
@ -128,19 +129,22 @@ main (
|
||||||
|
|
||||||
gPpiList = GetThunkPpiList ();
|
gPpiList = GetThunkPpiList ();
|
||||||
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
//
|
//
|
||||||
// We can't use dlopen on OS X, so we need a scheme to get symboles into gdb
|
// If dlopen doesn't work, then we build a gdb script to allow the
|
||||||
// We need to create a temp file that contains gdb commands so we can load
|
// symbols to be loaded.
|
||||||
// symbols when we load every PE/COFF image.
|
|
||||||
//
|
//
|
||||||
Index = strlen (*Argv);
|
Index = strlen (*Argv);
|
||||||
gGdbWorkingFileName = AllocatePool (Index + strlen(".gdb") + 1);
|
gGdbWorkingFileName = AllocatePool (Index + strlen(".gdb") + 1);
|
||||||
strcpy (gGdbWorkingFileName, *Argv);
|
strcpy (gGdbWorkingFileName, *Argv);
|
||||||
strcat (gGdbWorkingFileName, ".gdb");
|
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
|
// Allocate space for gSystemMemory Array
|
||||||
|
@ -1050,89 +1054,25 @@ PrintLoadAddress (
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VOID
|
/**
|
||||||
EFIAPI
|
Loads the image using dlopen so symbols will be automatically
|
||||||
SecPeCoffRelocateImageExtraAction (
|
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
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
BOOLEAN EnabledOnEntry;
|
|
||||||
|
|
||||||
//
|
return FALSE;
|
||||||
// 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.
|
|
||||||
// <library-list>
|
|
||||||
// <library name="/lib/libc.so.6"> // ImageContext->PdbPointer
|
|
||||||
// <segment address="0x10000000"/> // ImageContext->ImageAddress + ImageContext->SizeOfHeaders
|
|
||||||
// </library>
|
|
||||||
// </library-list>
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// 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 ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -1140,11 +1080,11 @@ SecPeCoffRelocateImageExtraAction (
|
||||||
void *Entry = NULL;
|
void *Entry = NULL;
|
||||||
|
|
||||||
if (ImageContext->PdbPointer == NULL) {
|
if (ImageContext->PdbPointer == NULL) {
|
||||||
return;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsPdbFile (ImageContext->PdbPointer)) {
|
if (!IsPdbFile (ImageContext->PdbPointer)) {
|
||||||
return;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf (
|
fprintf (
|
||||||
|
@ -1166,13 +1106,131 @@ SecPeCoffRelocateImageExtraAction (
|
||||||
if (Entry != NULL) {
|
if (Entry != NULL) {
|
||||||
ImageContext->EntryPoint = (UINTN)Entry;
|
ImageContext->EntryPoint = (UINTN)Entry;
|
||||||
printf ("Change %s Entrypoint to :0x%08lx\n", ImageContext->PdbPointer, (unsigned long)Entry);
|
printf ("Change %s Entrypoint to :0x%08lx\n", ImageContext->PdbPointer, (unsigned long)Entry);
|
||||||
|
return TRUE;
|
||||||
|
} else {
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SecUnixLoaderBreak ();
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
|
/**
|
||||||
|
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;
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
SecPeCoffRelocateImageExtraAction (
|
||||||
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!DlLoadImage (ImageContext)) {
|
||||||
|
GdbScriptAddImage (ImageContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
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 InterruptsWereEnabled;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Need to skip .PDB files created from VC++
|
||||||
|
//
|
||||||
|
if (IsPdbFile (ImageContext->PdbPointer)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SecInterruptEanbled ()) {
|
||||||
|
SecDisableInterrupt ();
|
||||||
|
InterruptsWereEnabled = TRUE;
|
||||||
|
} else {
|
||||||
|
InterruptsWereEnabled = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Write the file we need for the gdb script
|
||||||
|
//
|
||||||
|
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 ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1184,57 +1242,19 @@ SecPeCoffUnloadImageExtraAction (
|
||||||
{
|
{
|
||||||
VOID *Handle;
|
VOID *Handle;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check to see if the image symbols were loaded with gdb script, or dlopen
|
||||||
|
//
|
||||||
Handle = RemoveHandle (ImageContext);
|
Handle = RemoveHandle (ImageContext);
|
||||||
|
|
||||||
#ifdef __APPLE__
|
if (Handle == NULL) {
|
||||||
FILE *GdbTempFile;
|
#ifndef __APPLE__
|
||||||
BOOLEAN EnabledOnEntry;
|
|
||||||
|
|
||||||
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 ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
//
|
|
||||||
// Don't want to confuse gdb with symbols for something that got unloaded
|
|
||||||
//
|
|
||||||
if (Handle != NULL) {
|
|
||||||
dlclose (Handle);
|
dlclose (Handle);
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
GdbScriptRemoveImage (ImageContext);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue