Discussion:
[edk2] using gdb on OVMF with symbols
Duane Voth
2013-04-09 21:13:32 UTC
Permalink
previous thread was: [edk2] OVMF networking revisited
Spliting off this gdb+qemu+ovmf debugging discussion.
Versions:
qemu-kvm 1.2.0
gdb 7.5.1
OVMF X64 built on Linux with GCC 4.6
...
The error you are seeing means gdb does not have a type for
EFI_SYSTEM_TABLE so the file provided when you ran the command 'reload-uefi
/path/to/GdbSyms.dll' either was not there or did not have a symbol for
EFI_SYSTEM_TABLE. You can confirm this by running 'info types
EFI_SYSTEM_TABLE_POINTER' after you have run 'reload-uefi ...' It should
tell you there is nothing matching this type.
Here is Andrei's blog documenting GdbSyms:
http://osdevnotes.blogspot.com/2011/05/gdb-scripting-example-reloading-symbols.html

Let's get more concrete and use actual command lines:

term1: $ qemu-system-x86_64 -m 1024 -bios OVMF.fd -S -s -monitor stdio

term2: $ cd edk2/OvmfPkg
term2: $ gdb
term2: (gdb) target remote :1234
term2: (gdb) source ../../andreiw-wip/uefi/DebugPkg/Scripts/gdb_uefi.py
term2: (gdb) reload-uefi -o
../Build/AppPkg/DEBUG_GCC46/X64/AppPkg/Applications/GdbSyms/GdbSyms/DEBUG/GdbSyms.dll
term2: Python Exception <class 'gdb.error'> No type named
EFI_SYSTEM_TABLE_POINTER
term2:

As I understand his site, the above is how we're supposed to load and use
GdbSyms. I assumed that 2 years ago (when Andrei last used GdbSyms) that
no other command lines were needed and that over the last couple years only
symbol names might have changed.


An alternative approach that has provided some fruit is that I also have
.debug files in my edk2/Build directory which load into gdb. However,
since this is ROM/bootstrap code, the offsets need to be set manually.
(without using GdbSyms) I've managed to get this far using this alternate
approach:

term1: $ qemu-system-x86_64 -m 1024 -bios OVMF.fd -S -s -monitor stdio

term2: $ cd edk2/OvmfPkg
term2: $ gdb
term2: (gdb) target remote :1234
term2: (gdb) add-symbol-file ../Build/OvmfX64/DEBUG_GCC46/X64/SecMain.debug
0xfffcc2c4
term2: add symbol table from file
"../Build/OvmfX64/DEBUG_GCC46/X64/SecMain.debug" at
term2: .text_addr = 0xfffcc2c4
term2: (y or n) y
term2: Reading symbols from
/home/duanev/efi/edk2/Build/OvmfX64/DEBUG_GCC46/X64/SecMain.debug...done.
term2: (gdb)
term2: (gdb) info address FindMainFv
term2: Symbol "FindMainFv" is a function at address 0xfffcc2db.
term2: (gdb) info address EFI_SYSTEM_TABLE
term2: No symbol "EFI_SYSTEM_TABLE" in current context.
term2: (gdb) info type EFI_SYSTEM_TABLE_POINTER
term2: All types matching regular expression "EFI_SYSTEM_TABLE_POINTER":
term2: (gdb)

where 0xfffcc2c4 was determined empirically. At this point all the text
addresses line up correctly and single stepping isn't as barren a prospect,
however computing the load offset for the symbol table is I believe exactly
what Andrei managed to automate.
His script like mine use the system table pointer which as I said above is
only valid after DxeMain.efi is loaded. After a quick grep it looks like
AcpiTimerLibConstructor is only called from Dxe files so this should be ok.
Ovmf appears to be "a collection" of .efi files (again each with some new
offset). SecMain.debug (aka. SecMain.efi) seems to provide all the symbols
I need for my ACPI debugging, and that includes several of the modules in
the ovmf collection, but this is all a bit kludgy. I hope there is
something I'm missing...


Also you can read the i/o ports from qemu's monitor is the 'i' command or
from gdb with the 'monitor i' command.
Thanks for pointing this out. Interestingly, though, all my gdb 'monitor'
commands return blank lines with the exact count of the number of actual
lines they should have printed. :) I'll use the qemu command line for
now...
Andrew Fish
2013-04-09 21:45:29 UTC
Permalink
This post might be inappropriate. Click to display it.
Joe Vernaci
2013-04-10 03:20:25 UTC
Permalink
Thanks for making a new title it'll be easier to track...

Andrew is right those have not changed in quite a long time and even if
they did since GdbSyms builds against current headers it won't matter.

Gcc builds the .dll files as a self contained binary which is passed
through GenFw which if needed will convert elf binaries to pe/coff (efi)
binaries. But the mingw cross compiler (UNIXGCC toolchain) is capable of
producing pe/coff on it's own for use in Windows. So to strip and preserve
the debug symbols in the gcc produced pe/coff .dll files objcopy is used to
place them in a .debug file and use .gnu_debuglink to point the .dll to
that file. GenFw then makes a it's own link from the .efi to the .dll.
The .gnu_debuglink probably isn't needed anymore but it was used when GenFw
wasn't as capable as it is now.

Since I don't have GdbSyms I'll be using DxeCore.* since I know it has all
of the symbols you need. Also I'm using Ia32 since I seem to be having
issues with gdb-multiarch on x86_64.
$cd edk2/Build/OvmfIa32/DEBUG_GCC47/IA32$
$ objdump -s -j .debug DxeCore.efi

DxeCore.efi: file format pei-i386

Contents of section .debug:
288e0 00000000 00000000 00000000 02000000 ................
288f0 7d000000 fc880200 fc880200 4e423130 }...........NB10
28900 00000000 00000000 00000000 2f686f6d ............/hom
28910 652f6a6f 65766578 742f6769 742f6375 e/joevext/git/cu
28920 7474792f 65646b32 2f427569 6c642f4f tty/edk2/Build/O
28930 766d6649 6133322f 44454255 475f4743 vmfIa32/DEBUG_GC
28940 4334372f 49413332 2f4d6465 4d6f6475 C47/IA32/MdeModu
28950 6c65506b 672f436f 72652f44 78652f44 lePkg/Core/Dxe/D
28960 78654d61 696e2f44 45425547 2f447865 xeMain/DEBUG/Dxe
28970 436f7265 2e646c6c 00000000 00000000 Core.dll........
** This is the link created by GenFw when converting the elf .dll to
pe/coff .efi. This would be discovered on the running target by the python
scripts

$cd MdeModulePkg/Core/Dxe/DxeMain/DEBUG
$ objdump -s -j .gnu_debuglink DxeCore.dll

DxeCore.dll: file format elf32-i386

Contents of section .gnu_debuglink:
0000 44786543 6f72652e 64656275 67000000 DxeCore.debug...
0010 467942d7 FyB.
** This is the link created by objcopy --add-gnu-debuglink. This would be
followed automatically by gdb if DxeCore.dll was loaded with
[add-]symbol-file

$ objdump -Wi DxeCore.debug | grep EFI_SYSTEM_TABLE_POINTER
<df4a> DW_AT_name : (indirect string, offset: 0x44c5):
EFI_SYSTEM_TABLE_POINTER
** There's the symbol you need. Of course you should be doing this with
the GdbSyms.dll and as long as everything is there the problem is not the
symbol files. So for my case I this works and should be sort of what the
script is doing up to the type error you get.
$gdb-multiarch
(gdb) symbol-file DxeCore.dll
Reading symbols from
/home/joevext/git/cutty/edk2/Build/OvmfIa32/DEBUG_GCC47/IA32/MdeModulePkg/Core/Dxe/DxeMain/DEBUG/DxeCore.dll...Reading
symbols from
/home/joevext/git/cutty/edk2/Build/OvmfIa32/DEBUG_GCC47/IA32/MdeModulePkg/Core/Dxe/DxeMain/DEBUG/DxeCore.debug...done.
done.
(gdb) python print gdb.lookup_type('EFI_SYSTEM_TABLE_POINTER')
EFI_SYSTEM_TABLE_POINTER
(gdb)
I'm guessing what ever is going wrong may be getting buried in his
scripts...

Also some of my gdb monitor commands don't work either ... never could
figure out why so at least I'm not the only one. I see the packets going
over the remote just nothing ever happens.
Post by Duane Voth
previous thread was: [edk2] OVMF networking revisited
Spliting off this gdb+qemu+ovmf debugging discussion.
qemu-kvm 1.2.0
gdb 7.5.1
OVMF X64 built on Linux with GCC 4.6
...
The error you are seeing means gdb does not have a type for
EFI_SYSTEM_TABLE so the file provided when you ran the command 'reload-uefi
/path/to/GdbSyms.dll' either was not there or did not have a symbol for
EFI_SYSTEM_TABLE. You can confirm this by running 'info types
EFI_SYSTEM_TABLE_POINTER' after you have run 'reload-uefi ...' It should
tell you there is nothing matching this type.
http://osdevnotes.blogspot.com/2011/05/gdb-scripting-example-reloading-symbols.html
term1: $ qemu-system-x86_64 -m 1024 -bios OVMF.fd -S -s -monitor stdio
term2: $ cd edk2/OvmfPkg
term2: $ gdb
term2: (gdb) target remote :1234
term2: (gdb) source ../../andreiw-wip/uefi/DebugPkg/Scripts/gdb_uefi.py
term2: (gdb) reload-uefi -o
../Build/AppPkg/DEBUG_GCC46/X64/AppPkg/Applications/GdbSyms/GdbSyms/DEBUG/GdbSyms.dll
term2: Python Exception <class 'gdb.error'> No type named
EFI_SYSTEM_TABLE_POINTER
As I understand his site, the above is how we're supposed to load and use
GdbSyms. I assumed that 2 years ago (when Andrei last used GdbSyms) that
no other command lines were needed and that over the last couple years only
symbol names might have changed.
I don't think the symbols have changed. EFI_SYSTEM_TABLE_POINTER was in
the EFI spec a long time ago, and the types for cracking PE/COFF have not
changed for years now.
Given you don't know if the symbols are out of date that implies you are
using a binary GdbSyms.dll? Maybe there is some issues with your version of
gdb and the binary. I'd recommend you rebuilt GdbSyms from source and try
again.
An alternative approach that has provided some fruit is that I also have
.debug files in my edk2/Build directory which load into gdb. However,
since this is ROM/bootstrap code, the offsets need to be set manually.
(without using GdbSyms) I've managed to get this far using this alternate
term1: $ qemu-system-x86_64 -m 1024 -bios OVMF.fd -S -s -monitor stdio
term2: $ cd edk2/OvmfPkg
term2: $ gdb
term2: (gdb) target remote :1234
term2: (gdb) add-symbol-file
../Build/OvmfX64/DEBUG_GCC46/X64/SecMain.debug 0xfffcc2c4
term2: add symbol table from file
"../Build/OvmfX64/DEBUG_GCC46/X64/SecMain.debug" at
term2: .text_addr = 0xfffcc2c4
term2: (y or n) y
term2: Reading symbols from
/home/duanev/efi/edk2/Build/OvmfX64/DEBUG_GCC46/X64/SecMain.debug...done.
term2: (gdb)
term2: (gdb) info address FindMainFv
term2: Symbol "FindMainFv" is a function at address 0xfffcc2db.
term2: (gdb) info address EFI_SYSTEM_TABLE
term2: No symbol "EFI_SYSTEM_TABLE" in current context.
term2: (gdb) info type EFI_SYSTEM_TABLE_POINTER
term2: (gdb)
where 0xfffcc2c4 was determined empirically. At this point all the text
addresses line up correctly and single stepping isn't as barren a prospect,
however computing the load offset for the symbol table is I believe exactly
what Andrei managed to automate.
His script like mine use the system table pointer which as I said above
is only valid after DxeMain.efi is loaded. After a quick grep it looks
like AcpiTimerLibConstructor is only called from Dxe files so this should
be ok.
Ovmf appears to be "a collection" of .efi files (again each with some new
offset). SecMain.debug (aka. SecMain.efi) seems to provide all the symbols
I need for my ACPI debugging, and that includes several of the modules in
the ovmf collection, but this is all a bit kludgy. I hope there is
something I'm missing...
Also you can read the i/o ports from qemu's monitor is the 'i' command or
from gdb with the 'monitor i' command.
Thanks for pointing this out. Interestingly, though, all my gdb 'monitor'
commands return blank lines with the exact count of the number of actual
lines they should have printed. :) I'll use the qemu command line for
now...
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter_______________________________________________
edk2-devel mailing list
https://lists.sourceforge.net/lists/listinfo/edk2-devel
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
edk2-devel mailing list
https://lists.sourceforge.net/lists/listinfo/edk2-devel
Duane Voth
2013-04-10 22:12:19 UTC
Permalink
Post by Joe Vernaci
Thanks for making a new title it'll be easier to track...
Andrew is right those have not changed in quite a long time and even if
they did since GdbSyms builds against current headers it won't matter.
Gcc builds the .dll files as a self contained binary which is passed
through GenFw which if needed will convert elf binaries to pe/coff (efi)
binaries. But the mingw cross compiler (UNIXGCC toolchain) is capable of
producing pe/coff on it's own for use in Windows. So to strip and preserve
the debug symbols in the gcc produced pe/coff .dll files objcopy is used to
place them in a .debug file and use .gnu_debuglink to point the .dll to
that file. GenFw then makes a it's own link from the .efi to the .dll.
The .gnu_debuglink probably isn't needed anymore but it was used when GenFw
wasn't as capable as it is now.
Ok so apparently I should have been loading .debug files instead of .dll
files. :p The following (without recompiling anything) gets pretty far
along:

term1: $ qemu-system-x86_64 -m 1024 -bios OVMF.fd -S -s -monitor stdio

term2: $ cd edk2/OvmfPkg
term2: $ gdb
term2: (gdb) target remote :1234
term2: (gdb) c
-- wait 5 seconds
ctrl-c
-- gdb complains several times about Remote 'g' packet reply is too long --
term2: (gdb) set arch i386:x86-64
term2: (gdb) source ../../andreiw-wip/uefi/DebugPkg/Scripts/gdb_uefi.py
term2: (gdb) reload-uefi -o ../Build/AppPkg/DEBUG_GCC46/X64/GdbSyms.debug
EFI_SYSTEM_TABLE @ 0x3fb59f18
Connected to EDK II (Rev. 0x10000)
ConfigurationTable @ 0x3fb58e18, 0x8 entries
DebugImageInfoTable @ 0x3f980018, 0x39 entries
Loading new symbols...
add-symbol-file
/home/duanev/efi/edk2/Build/OvmfX64/DEBUG_GCC46/X64/MdeModulePkg/Core/Dxe/DxeMain/DEBUG/DxeCore.debug
0x3fbcd260
add symbol table from file
"/home/duanev/efi/edk2/Build/OvmfX64/DEBUG_GCC46/X64/MdeModulePkg/Core/Dxe/DxeMain/DEBUG/DxeCore.debug"
at
.text_addr = 0x3fbcd260
add-symbol-file
/home/duanev/efi/edk2/Build/OvmfX64/DEBUG_GCC46/X64/MdeModulePkg/Universal/PCD/Dxe/Pcd/DEBUG/PcdDxe.debug
0x3fafc260
...

So when I symbol-file load GdbSyms.debug instead of GdbSyms.dll,
EFI_SYSTEM_TABLE_POINTER is fine.

Now since in-memory values are used to compute load addresses, I have to
let OVMF execute a ways before running reload-uefi. Fortunately my current
problem is a hang, so I can simply ctrl-c gdb to make it stop in a useful
place, and then run reload-uefi. Breakpoints don't work for me yet so this
will have to do (besides breakpoints are going to be messy with the cpu
mode switches and multiple memory maps).

I also modded GdbSyms.py to load .debug files instead of .dlls, and now I
can get all the way to:

...
add-symbol-file
/home/duanev/efi/edk2/Build/OvmfX64/DEBUG_GCC46/X64/OvmfPkg/QemuVideoDxe/QemuVideoDxe/DEBUG/QemuVideoDxe.debug
0x3e559260
add symbol table from file
"/home/duanev/efi/edk2/Build/OvmfX64/DEBUG_GCC46/X64/OvmfPkg/QemuVideoDxe/QemuVideoDxe/DEBUG/QemuVideoDxe.debug"
at
.text_addr = 0x3e559260
add-symbol-file
/home/jljusten/dev/edk2/Build/OvmfX64/RELEASE_GCC44/X64/OptionRomPkg/CirrusLogic5430Dxe/CirrusLogic5430Dxe/DEBUG/CirrusLogic5430Dxe.debug
0x3e552260
add symbol table from file
"/home/jljusten/dev/edk2/Build/OvmfX64/RELEASE_GCC44/X64/OptionRomPkg/CirrusLogic5430Dxe/CirrusLogic5430Dxe/DEBUG/CirrusLogic5430Dxe.debug"
at
.text_addr = 0x3e552260
Python Exception <class 'gdb.error'>
/home/jljusten/dev/edk2/Build/OvmfX64/RELEASE_GCC44/X64/OptionRomPkg/CirrusLogic5430Dxe/CirrusLogic5430Dxe/DEBUG/CirrusLogic5430Dxe.debug:
No such file or directory.:
(gdb)

As I recall the Cirrus driver was recently turned off? For the moment I've
explicitly skipped the load of the CirrusLogic symtable.


Now I can do:

(gdb) info address mDxeServices
Symbol "mDxeServices" is static storage at address 0x315a0.
(gdb) print mDxeServices
$2 = {Hdr = {Signature = 0, Revision = 0, HeaderSize = 0, CRC32 = 0,
Reserved = 0}, AddMemorySpace = 0x0,
AllocateMemorySpace = 0x0, FreeMemorySpace = 0x0, RemoveMemorySpace =
0x0,
GetMemorySpaceDescriptor = 0x0, SetMemorySpaceAttributes = 0x0,
GetMemorySpaceMap = 0x0,
AddIoSpace = 0x0, AllocateIoSpace = 0x0, FreeIoSpace = 0x0, RemoveIoSpace
= 0x0,
GetIoSpaceDescriptor = 0x0, GetIoSpaceMap = 0x0, Dispatch = 0x0, Schedule
= 0x0, Trust = 0x0,
ProcessFirmwareVolume = 0x0}

Not all is good yet as obviously these values should not be zero...
probably an initial offset problem.

It also appears that only device driver symbols are being loaded - which
makes sense as this is what Andrei was helping GsoC with. I'll need to get
a few more modules loaded as there are no symbols yet for the area of code
I'm trying to debug.
Andrew Fish
2013-04-10 22:21:54 UTC
Permalink
Duane,

You can place CpuBreakpoint (); (it is a member of the BaseLib) in your code and cause a break into GDB.

Andrew Fish
Post by Joe Vernaci
Thanks for making a new title it'll be easier to track...
Andrew is right those have not changed in quite a long time and even if they did since GdbSyms builds against current headers it won't matter.
Gcc builds the .dll files as a self contained binary which is passed through GenFw which if needed will convert elf binaries to pe/coff (efi) binaries. But the mingw cross compiler (UNIXGCC toolchain) is capable of producing pe/coff on it's own for use in Windows. So to strip and preserve the debug symbols in the gcc produced pe/coff .dll files objcopy is used to place them in a .debug file and use .gnu_debuglink to point the .dll to that file. GenFw then makes a it's own link from the .efi to the .dll. The .gnu_debuglink probably isn't needed anymore but it was used when GenFw wasn't as capable as it is now.
term1: $ qemu-system-x86_64 -m 1024 -bios OVMF.fd -S -s -monitor stdio
term2: $ cd edk2/OvmfPkg
term2: $ gdb
term2: (gdb) target remote :1234
term2: (gdb) c
-- wait 5 seconds
ctrl-c
-- gdb complains several times about Remote 'g' packet reply is too long --
term2: (gdb) set arch i386:x86-64
term2: (gdb) source ../../andreiw-wip/uefi/DebugPkg/Scripts/gdb_uefi.py
term2: (gdb) reload-uefi -o ../Build/AppPkg/DEBUG_GCC46/X64/GdbSyms.debug
Connected to EDK II (Rev. 0x10000)
Loading new symbols...
add-symbol-file /home/duanev/efi/edk2/Build/OvmfX64/DEBUG_GCC46/X64/MdeModulePkg/Core/Dxe/DxeMain/DEBUG/DxeCore.debug 0x3fbcd260
add symbol table from file "/home/duanev/efi/edk2/Build/OvmfX64/DEBUG_GCC46/X64/MdeModulePkg/Core/Dxe/DxeMain/DEBUG/DxeCore.debug" at
.text_addr = 0x3fbcd260
add-symbol-file /home/duanev/efi/edk2/Build/OvmfX64/DEBUG_GCC46/X64/MdeModulePkg/Universal/PCD/Dxe/Pcd/DEBUG/PcdDxe.debug 0x3fafc260
...
So when I symbol-file load GdbSyms.debug instead of GdbSyms.dll, EFI_SYSTEM_TABLE_POINTER is fine.
Now since in-memory values are used to compute load addresses, I have to let OVMF execute a ways before running reload-uefi. Fortunately my current problem is a hang, so I can simply ctrl-c gdb to make it stop in a useful place, and then run reload-uefi. Breakpoints don't work for me yet so this will have to do (besides breakpoints are going to be messy with the cpu mode switches and multiple memory maps).
...
add-symbol-file /home/duanev/efi/edk2/Build/OvmfX64/DEBUG_GCC46/X64/OvmfPkg/QemuVideoDxe/QemuVideoDxe/DEBUG/QemuVideoDxe.debug 0x3e559260
add symbol table from file "/home/duanev/efi/edk2/Build/OvmfX64/DEBUG_GCC46/X64/OvmfPkg/QemuVideoDxe/QemuVideoDxe/DEBUG/QemuVideoDxe.debug" at
.text_addr = 0x3e559260
add-symbol-file /home/jljusten/dev/edk2/Build/OvmfX64/RELEASE_GCC44/X64/OptionRomPkg/CirrusLogic5430Dxe/CirrusLogic5430Dxe/DEBUG/CirrusLogic5430Dxe.debug 0x3e552260
add symbol table from file "/home/jljusten/dev/edk2/Build/OvmfX64/RELEASE_GCC44/X64/OptionRomPkg/CirrusLogic5430Dxe/CirrusLogic5430Dxe/DEBUG/CirrusLogic5430Dxe.debug" at
.text_addr = 0x3e552260
(gdb)
As I recall the Cirrus driver was recently turned off? For the moment I've explicitly skipped the load of the CirrusLogic symtable.
(gdb) info address mDxeServices
Symbol "mDxeServices" is static storage at address 0x315a0.
(gdb) print mDxeServices
$2 = {Hdr = {Signature = 0, Revision = 0, HeaderSize = 0, CRC32 = 0, Reserved = 0}, AddMemorySpace = 0x0,
AllocateMemorySpace = 0x0, FreeMemorySpace = 0x0, RemoveMemorySpace = 0x0,
GetMemorySpaceDescriptor = 0x0, SetMemorySpaceAttributes = 0x0, GetMemorySpaceMap = 0x0,
AddIoSpace = 0x0, AllocateIoSpace = 0x0, FreeIoSpace = 0x0, RemoveIoSpace = 0x0,
GetIoSpaceDescriptor = 0x0, GetIoSpaceMap = 0x0, Dispatch = 0x0, Schedule = 0x0, Trust = 0x0,
ProcessFirmwareVolume = 0x0}
Not all is good yet as obviously these values should not be zero... probably an initial offset problem.
It also appears that only device driver symbols are being loaded - which makes sense as this is what Andrei was helping GsoC with. I'll need to get a few more modules loaded as there are no symbols yet for the area of code I'm trying to debug.
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter_______________________________________________
edk2-devel mailing list
https://lists.sourceforge.net/lists/listinfo/edk2-devel
Andrei E. Warkentin
2013-04-11 04:27:59 UTC
Permalink
Hiya guys,

Sorry for being late. Duane had emailed me privately as well, but I just
hadn't gotten around to it all yet...

Anyway. Interesting about the .debug files. Something must have changed -
couple of years back during the first Xen GSoC it all worked fine with the
.dll files.

Feel free to send me any patches to apply. Wouldn't want to have a useful
tool bitrot.

Now - about looking at actual symbols. There's a different problem here.
GDB doesn't deal very well with EFI in that it doesn't deal well with
multiple modules with the same symbols. So the script is loading all the
symbols (for all modules in the module list anyway), but you won't be able
to look at the symbols you want all the time.

This is why I had developed module scope.

https://github.com/andreiw/andreiw-wip/blob/master/gdb/0001-GDB-Initial-prototype-of-symbol-file-scope-module-sc.patch

You can do stuff like:

Print &'DxeCore.dll'::gST


Never got around to going through the paper tape ("prove your stuff doesn't
break gdb") to merge this into mainline, but there it is. Should be
relatively simple to apply to a newer gdb code base. This shouldn't have
rotted too much in two years.

A
Post by Joe Vernaci
Thanks for making a new title it'll be easier to track...
Post by Joe Vernaci
Andrew is right those have not changed in quite a long time and even if
they did since GdbSyms builds against current headers it won't matter.
Gcc builds the .dll files as a self contained binary which is passed
through GenFw which if needed will convert elf binaries to pe/coff (efi)
binaries. But the mingw cross compiler (UNIXGCC toolchain) is capable of
producing pe/coff on it's own for use in Windows. So to strip and preserve
the debug symbols in the gcc produced pe/coff .dll files objcopy is used to
place them in a .debug file and use .gnu_debuglink to point the .dll to
that file. GenFw then makes a it's own link from the .efi to the .dll.
The .gnu_debuglink probably isn't needed anymore but it was used when GenFw
wasn't as capable as it is now.
Ok so apparently I should have been loading .debug files instead of .dll
files. :p The following (without recompiling anything) gets pretty far
term1: $ qemu-system-x86_64 -m 1024 -bios OVMF.fd -S -s -monitor stdio
term2: $ cd edk2/OvmfPkg
term2: $ gdb
term2: (gdb) target remote :1234
term2: (gdb) c
-- wait 5 seconds
ctrl-c
-- gdb complains several times about Remote 'g' packet reply is too long --
term2: (gdb) set arch i386:x86-64
term2: (gdb) source ../../andreiw-wip/uefi/DebugPkg/Scripts/gdb_uefi.py
term2: (gdb) reload-uefi -o ../Build/AppPkg/DEBUG_GCC46/X64/GdbSyms.debug
Connected to EDK II (Rev. 0x10000)
Loading new symbols...
add-symbol-file
/home/duanev/efi/edk2/Build/OvmfX64/DEBUG_GCC46/X64/MdeModulePkg/Core/Dxe/DxeMain/DEBUG/DxeCore.debug
0x3fbcd260
add symbol table from file
"/home/duanev/efi/edk2/Build/OvmfX64/DEBUG_GCC46/X64/MdeModulePkg/Core/Dxe/DxeMain/DEBUG/DxeCore.debug"
at
.text_addr = 0x3fbcd260
add-symbol-file
/home/duanev/efi/edk2/Build/OvmfX64/DEBUG_GCC46/X64/MdeModulePkg/Universal/PCD/Dxe/Pcd/DEBUG/PcdDxe.debug
0x3fafc260
...
So when I symbol-file load GdbSyms.debug instead of GdbSyms.dll,
EFI_SYSTEM_TABLE_POINTER is fine.
Now since in-memory values are used to compute load addresses, I have to
let OVMF execute a ways before running reload-uefi. Fortunately my current
problem is a hang, so I can simply ctrl-c gdb to make it stop in a useful
place, and then run reload-uefi. Breakpoints don't work for me yet so this
will have to do (besides breakpoints are going to be messy with the cpu
mode switches and multiple memory maps).
I also modded GdbSyms.py to load .debug files instead of .dlls, and now I
...
add-symbol-file
/home/duanev/efi/edk2/Build/OvmfX64/DEBUG_GCC46/X64/OvmfPkg/QemuVideoDxe/QemuVideoDxe/DEBUG/QemuVideoDxe.debug
0x3e559260
add symbol table from file
"/home/duanev/efi/edk2/Build/OvmfX64/DEBUG_GCC46/X64/OvmfPkg/QemuVideoDxe/QemuVideoDxe/DEBUG/QemuVideoDxe.debug"
at
.text_addr = 0x3e559260
add-symbol-file
/home/jljusten/dev/edk2/Build/OvmfX64/RELEASE_GCC44/X64/OptionRomPkg/CirrusLogic5430Dxe/CirrusLogic5430Dxe/DEBUG/CirrusLogic5430Dxe.debug
0x3e552260
add symbol table from file
"/home/jljusten/dev/edk2/Build/OvmfX64/RELEASE_GCC44/X64/OptionRomPkg/CirrusLogic5430Dxe/CirrusLogic5430Dxe/DEBUG/CirrusLogic5430Dxe.debug"
at
.text_addr = 0x3e552260
Python Exception <class 'gdb.error'>
(gdb)
As I recall the Cirrus driver was recently turned off? For the moment
I've explicitly skipped the load of the CirrusLogic symtable.
(gdb) info address mDxeServices
Symbol "mDxeServices" is static storage at address 0x315a0.
(gdb) print mDxeServices
$2 = {Hdr = {Signature = 0, Revision = 0, HeaderSize = 0, CRC32 = 0,
Reserved = 0}, AddMemorySpace = 0x0,
AllocateMemorySpace = 0x0, FreeMemorySpace = 0x0, RemoveMemorySpace =
0x0,
GetMemorySpaceDescriptor = 0x0, SetMemorySpaceAttributes = 0x0,
GetMemorySpaceMap = 0x0,
AddIoSpace = 0x0, AllocateIoSpace = 0x0, FreeIoSpace = 0x0,
RemoveIoSpace = 0x0,
GetIoSpaceDescriptor = 0x0, GetIoSpaceMap = 0x0, Dispatch = 0x0,
Schedule = 0x0, Trust = 0x0,
ProcessFirmwareVolume = 0x0}
Not all is good yet as obviously these values should not be zero...
probably an initial offset problem.
It also appears that only device driver symbols are being loaded - which
makes sense as this is what Andrei was helping GsoC with. I'll need to get
a few more modules loaded as there are no symbols yet for the area of code
I'm trying to debug.
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
edk2-devel mailing list
https://lists.sourceforge.net/lists/listinfo/edk2-devel
--
A
Duane Voth
2013-04-11 13:04:56 UTC
Permalink
Thanks Andrew, I'll give CpuBreakpoint() a try. Is there a good place you
know of where to place a startup breakpoint so that all the system data
structures are in place (and Andrei's script will run properly)?

Andrei - ouch that syntax :) Is there anyway we can get to DxeCore.gST ?
Perhaps GenFw... Will send patches as I gain certainty I'm doing it
right! However it seems that the two (or more?) environments want
different answers - my patches for GCC will likely break the greater
numbers using MSC - I'm not willing to do that...
Andrew Fish
2013-04-11 15:37:06 UTC
Permalink
Thanks Andrew, I'll give CpuBreakpoint() a try. Is there a good place you know of where to place a startup breakpoint so that all the system data structures are in place (and Andrei's script will run properly)?
I usually just place it in the entry point of failing driver.

The serial output has a lot of info about where you are in the boot process. This is the output of the EmulatorPkg....

Switch from IA32 to X64 happens in DXE IPL to load DXE Core (produces EFI Services):
DXE IPL Entry
0x106f58240 Loading /Users/fish/work/edk2TOT/Build/Emulator/DEBUG_XCLANG/X64/MdeModulePkg/Core/Dxe/DxeMain/DEBUG/DxeCore.dll with entry point 0x106f5c390
Loading PEIM at 0x00106F58000 EntryPoint=0x00106F5C390 DxeCore.efi
PROGRESS CODE: V3021001 I0
Loading DXE CORE at 0x00106F58000 EntryPoint=0x00106F5C390
Install PPI: 605EA650-C65C-42E1-BA80-91A52AB618C6
0x106f58000 Loading /Users/fish/work/edk2TOT/Build/Emulator/DEBUG_XCLANG/X64/MdeModulePkg/Core/Dxe/DxeMain/DEBUG/DxeCore.dll with entry point 0x00000000
HOBLIST address in DXE = 0x106F31018
Memory Allocation 0x00000004 0x106F38000 - 0x106F57FFF
Memory Allocation 0x00000004 0x106FFF000 - 0x106FFFFFF
Memory Allocation 0x00000004 0x106FE9000 - 0x106FFEFFF
Memory Allocation 0x00000004 0x106FE6000 - 0x106FE8FFF
Memory Allocation 0x00000004 0x106FE3000 - 0x106FE5FFF
Memory Allocation 0x00000004 0x106FE0000 - 0x106FE2FFF
Memory Allocation 0x00000004 0x106FDB000 - 0x106FDFFFF
Memory Allocation 0x00000004 0x106FD1000 - 0x106FDAFFF
Memory Allocation 0x00000004 0x106FCD000 - 0x106FD0FFF
Memory Allocation 0x00000004 0x106F92000 - 0x106FCCFFF
Memory Allocation 0x00000004 0x106F58000 - 0x106F91FFF
Memory Allocation 0x00000003 0x106F58000 - 0x106F91FFF
Memory Allocation 0x00000004 0x106F38000 - 0x106F57FFF
Memory Allocation 0x00000004 0x103000000 - 0x10301FFFF
FV Hob 0x102000000 - 0x10257FFFF
FV Hob 0x102580000 - 0x10259FFFF
InstallProtocolInterface: D8117CFE-94A6-11D4-9A3A-0090273FC14D 106F8ED78
InstallProtocolInterface: 8F644FA9-E850-4DB1-9CE2-0B44698E8DA4 106F2DD30
InstallProtocolInterface: 09576E91-6D3F-11D2-8E39-00A0C969723B 106F2E818
InstallProtocolInterface: 8F644FA9-E850-4DB1-9CE2-0B44698E8DA4 106F2DC30
InstallProtocolInterface: 09576E91-6D3F-11D2-8E39-00A0C969723B 106F2E498
InstallProtocolInterface: 220E73B6-6BDB-4413-8405-B974B108619A 106F2DA30
InstallProtocolInterface: EE4E5898-3914-4259-9D6E-DC7BD79403CF 106F8DCA8
InstallProtocolInterface: FC1BCDB0-7D31-49AA-936A-A4600D9DD083 106F8DCA8
InstallProtocolInterface: A31280AD-481E-41B6-95E8-127F4C984779 106F8DCA8

The DXE Core dispatches drivers and you see that info like:
Loading driver 80CF7257-87AB-47F9-A3FE-D50B76D89541
InstallProtocolInterface: 5B1B31A1-9562-11D2-8E3F-00A0C969723B 106D08E40
0x1064ee240 Loading /Users/fish/work/edk2TOT/Build/Emulator/DEBUG_XCLANG/X64/MdeModulePkg/Universal/PCD/Dxe/Pcd/DEBUG/PcdDxe.dll with entry point 0x1064f0de0
Loading driver at 0x001064EE000 EntryPoint=0x001064F0DE0 PcdDxe.efi

The DEBUG print for "Loading driver at " is coming from: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2/MdeModulePkg/Core/Dxe/Image/Image.c

Note the long form of the info is coming out of the gdb script in the emulator
0x1064ee240 Loading /Users/fish/work/edk2TOT/Build/Emulator/DEBUG_XCLANG/X64/MdeModulePkg/Universal/PCD/Dxe/Pcd/DEBUG/PcdDxe.dll with entry point 0x1064f0de0


I don't use gdb, I've converted to lldb. But with the Xcode version of gdb you had to tell gdb what processor architecture you were using since you start without a target. So you may just get the default processor mode that was compiled into gdb when you launch it.

Thanks,

Andrew Fish
Andrei - ouch that syntax :) Is there anyway we can get to DxeCore.gST ? Perhaps GenFw... Will send patches as I gain certainty I'm doing it right! However it seems that the two (or more?) environments want different answers - my patches for GCC will likely break the greater numbers using MSC - I'm not willing to do that...
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter_______________________________________________
edk2-devel mailing list
https://lists.sourceforge.net/lists/listinfo/edk2-devel
Duane Voth
2013-04-23 21:30:26 UTC
Permalink
So CpuBreakpoint(), or just asm volatile ("int3"); , still won't transfer
control to gdb. :(

asm volatile ("xx: jmp xx;"); however allows me to use ctrl-c in gdb.

I was hoping the following would be of great help:

Index: ShellPkg/Application/Shell/ShellProtocol.c
===================================================================
--- ShellPkg/Application/Shell/ShellProtocol.c (revision 14307)
+++ ShellPkg/Application/Shell/ShellProtocol.c (working copy)
@@ -1496,6 +1496,8 @@
Status = gBS->InstallProtocolInterface(&NewHandle,
&gEfiShellParametersProtocolGuid, EFI_NATIVE_INTERFACE,
&ShellParamsProtocol);
ASSERT_EFI_ERROR(Status);

+ ShellPrintEx(-1, -1, L"+++ ld: 0x%x\r\n", LoadedImage->ImageBase);
+
///@todo initialize and install ShellInterface protocol on the new
image for compatibility if - PcdGetBool(PcdShellSupportOldProtocols)

//

and combined with:

(gdb) add-symbol-file
../Build/AppPkg/DEBUG_GCC46/X64/AppPkg/Applications/Python/PythonCore/DEBUG/Python.debug
0x3cb3a000

it gives me something close but the function in which I placed the
loop-forever is 0x260 bytes higher up in memory. So I can adjust the load
address by 0x260 and, VoilĂ , I have symbolic debugging! (for this shell
loaded app) But is 0x260 a constant or is it going to change?

So nice to have the 'n' step-over command working! :)

(note: this is qemu 1.4.0, gdb 7.5.1, gcc 4.7.1 but building with -t GCC46,
and without Andrei's sym loader - so I cant step into system calls)
Loading...