Hi Laszlo, On Wed, Jun 18, 2014 at 11:34:45PM +0200, Laszlo Ersek wrote: > This is a longish and quite raw email, but (for me at least) a big > improvement, so I'll share my findings here. > Thanks for your sharing. I followed the steps and saw the backtrace in gdb. This is exactly something I am longing for!
What wasn't mentioned is the debug file path in BaseTools/Conf/tools_def.template needs a fix like this: - DEBUG_*_*_OBJCOPY_ADDDEBUGFLAG = --add-gnu-debuglink=$(DEBUG_DIR)\$(MODULE_NAME).debug + DEBUG_*_*_OBJCOPY_ADDDEBUGFLAG = --add-gnu-debuglink=$(DEBUG_DIR)/$(MODULE_NAME).debug It took me a while to find out why the symbols were missing in GdbSyms.dll. Besides, I had some strange error messages while executing "reload-uefi -o": add-symbol-file 8086100e.efidrv 0x68c82c0 add symbol table from file "8086100e.efidrv" at .text_addr = 0x68c82c0 Python Exception <class 'gdb.error'> 8086100e.efidrv: No such file or directory.: Error occurred in Python command: 8086100e.efidrv: No such file or directory. However, "bt" still worked, and I can poke the local variables. Probably a glitch in the script, but it didn't harm anyway. Thanks, Gary Lin > (1) Clone Andrei Warkentin's repo > <https://github.com/andreiw/andreiw-wip.git>. The commit I'm testing at > is 1ab3fa97. > > git clone https://github.com/andreiw/andreiw-wip.git > cd andreiw-wip > git checkout 1ab3fa97 > > (2) From the root of your clone copy the subdirectory "uefi/DebugPkg" to > your edk2 workspace: > > cp -av uefi/DebugPkg $WORKSPACE > > (3) Apply the following patch to OvmfPkg/OvmfPkgX64.dsc: > > ----------------- > diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc > index 97fdedb..794521b 100644 > --- a/OvmfPkg/OvmfPkgX64.dsc > +++ b/OvmfPkg/OvmfPkgX64.dsc > @@ -592,3 +592,4 @@ > !endif > > OvmfPkg/PlatformDxe/Platform.inf > + DebugPkg/GdbSyms/GdbSyms.inf > ----------------- > > Note that we don't modify the FDF file. > > (4) Build OVMF (X64) as usual. Don't clean the build directory. > > (5) Start OVMF in qemu. Pass the "-s" option to qemu. (Shorthand for > "-gdb tcp::1234"). > > (6) Start gdb in another terminal, and issue the following commands: > > (gdb) set architecture i386:x86-64:intel > (gdb) target remote localhost:1234 > (gdb) source [WORKSPACE]/DebugPkg/Scripts/gdb_uefi.py > (gdb) reload-uefi -o > [WORKSPACE]/Build/OvmfX64/DEBUG_GCC48/X64/DebugPkg/GdbSyms/GdbSyms/DEBUG/GdbSyms.dll > > (7) Issue "bt" at the gdb prompt: > > (gdb) bt > > ... And then you'll get a stack trace, but the local variables cannot be > displayed. Each will be reported as: > > <error reading variable: can't compute CFA for this frame> > > In order to fix this, we must understand the above procedure, so let's > see the explanation (sometimes quite the hand-waving, sorry). > > (a) Andrei's DebugPkg/GdbSyms module does nothing at all. We don't even > include it in the final firmware image (see the note about the FDF in > (3)). > > The reason we need it because it uses the following *types*: > > EFI_SYSTEM_TABLE_POINTER > EFI_DEBUG_IMAGE_INFO_TABLE_HEADER > EFI_IMAGE_DOS_HEADER > EFI_IMAGE_OPTIONAL_HEADER_UNION > EFI_IMAGE_DEBUG_DIRECTORY_ENTRY > EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY > EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY > EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY > > When we build the tree in (4), the layout of the above structures > (names, fields, offsets -- basically the type definitions) will be > generated into the GdbSyms.dll file, as debug symbols. > > (b) The "DebugPkg/Scripts/gdb_uefi.py" script is a gdb extension (a new > command), written in Python. It is run "under" gdb, and can communicate > with gdb in a programmatic fashion. It can peek and poke at memory, cast > pointers, ie. whatever you can do at the gdb prompt, but it can do it > algorithmically. > > The script defines a new command, "reload-uefi". "reload-uefi" does the > following: > > (b1) it loads the *type information* for the structures listed under > (a), from the GdbSyms.dll file. GdbSyms.dll is used for nothing else. > > (b2) It locates the EFI system table in (guest) memory, looking at each > multiple of 4MB, checking for the signature and verifying the CRC. > > (b3) When the system table is found, it follows a long chain of pointers > and structures (relying heavily on the struct types from (a)) until it > lands on the list of loaded EFI images. > > (b4) It iterates over the list of loaded EFI images. For each image: > - it reads the header that identifies the "debug symbols file" for the > image, > - it makes gdb load that symbol file, > - and it asks gdb to "foist" that symbol file on the base address of > the loaded image in question. > > The "debug symbols file" is just the dll file in the Build directory. > Eg. for "QemuVideoDxe.efi", it is "QemuVideoDxe.dll" (with full, > absolute path under $WORKSPACE of course). > > (c) The "bt" command in (7) should just work, but it doesn't really. > > > The problem is that for local variables to be displayed, the .eh_frame > section should be present in the DLL files (eg. QemuVideoDxe.dll), but > it is absent. > > https://refspecs.linuxbase.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html > > It is absent for a reason: GenFw cannot cope with (relocation entries > for) .eh_frame sections. We've discussed this earlier on the list, but > for illustration it is simplest to look at the build log. I'm removing > the longest common prefix from pathnames, for readability: > > > "ld" -o QemuVideoDxe.dll ... \ > > --script=.../BaseTools/Scripts/gcc4.4-ld-script ... > > In this step, QemuVideoDxe.dll is created. The referenced linker script > contains > > .eh_frame ALIGN(0x20) : > { > KEEP (*(.eh_frame)) > } > > so the DLL does contain an eh_frame section at this point. > > > "objcopy" QemuVideoDxe.dll > > Not sure why this is useful, I think this command does nothing. > > > cp -f QemuVideoDxe.dll QemuVideoDxe.debug > > Aha! The DLL, with the .eh_frame section, is saved as > "QemuVideoDxe.debug". > > > objcopy --strip-unneeded -R .eh_frame QemuVideoDxe.dll > > The .eh_frame section is hereby removed from the DLL. > > > objcopy --add-gnu-debuglink=QemuVideoDxe.debug QemuVideoDxe.dll > > This adds a .gnu_debuglink section to the DLL, pointing at the > "QemuVideoDxe.debug" file. (Only the last pathname component, ie. the > filename, is saved, in that section.) > > This might be helpful for other debugging solutions, but it doesn't seem > to help with qemu+gdb at all. > > > "GenFw" -e UEFI_DRIVER -o QemuVideoDxe.efi QemuVideoDxe.dll > > This is where GenFw converts the DLL to an EFI executable. > > *If* we had the .eh_frame section still present in the DLL, this command > would fail, because GenFw doesn't know how to handle .eh_frame. > > (More precisely: it doesn't know how to handle relocations for > .eh_frame, ie. '.rela.eh_frame'. See the discussion at > <http://thread.gmane.org/gmane.comp.bios.tianocore.devel/3796/focus=3800>.) > > Because the build process has removed the .eh_frame (and the referrer > .rela.eh_frame) sections, GenFw succeeds. But, as a consequence, the DLL > file will *also* be unusable for printing local variables, because it > has no (or insufficient) call frame information. > > The solution (or at least "one" solution) is to update Andrei's gdb > script. Rather than loading the DLL file for the EFI file (see (b4)), > let's load the DEBUG file immediately. The DEBUG file is the original > version of the DLL file, ie. from before the stripping. > > Hence, after step (2), before step (3), the following patch should be > applied: > > ----------------- > --- DebugPkg/Scripts/gdb_uefi.py.orig 2014-06-18 22:36:42.131171623 +0200 > +++ DebugPkg/Scripts/gdb_uefi.py 2014-06-18 23:24:56.086566783 +0200 > @@ -18,6 +18,7 @@ > import array > import getopt > import binascii > +import re > > __license__ = "BSD" > __version = "1.0.0" > @@ -243,6 +244,7 @@ > base = base + opt['SizeOfHeaders'] > if sym_name != self.EINVAL: > sym_name = sym_name.cast (self.ptype('CHAR8')).string () > + sym_name = re.sub(r"\.dll$", ".debug", sym_name) > syms.append ("add-symbol-file %s 0x%x" % \ > (sym_name, > long (base))) > ----------------- > > And then local variables are displayed too. > > Thanks, > Laszlo > > ------------------------------------------------------------------------------ > HPCC Systems Open Source Big Data Platform from LexisNexis Risk Solutions > Find What Matters Most in Your Big Data with HPCC Systems > Open Source. Fast. Scalable. Simple. Ideal for Dirty Data. > Leverages Graph Analysis for Fast Processing & Easy Data Exploration > http://p.sf.net/sfu/hpccsystems > _______________________________________________ > edk2-devel mailing list > edk2-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/edk2-devel > ------------------------------------------------------------------------------ HPCC Systems Open Source Big Data Platform from LexisNexis Risk Solutions Find What Matters Most in Your Big Data with HPCC Systems Open Source. Fast. Scalable. Simple. Ideal for Dirty Data. Leverages Graph Analysis for Fast Processing & Easy Data Exploration http://p.sf.net/sfu/hpccsystems _______________________________________________ edk2-devel mailing list edk2-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/edk2-devel