[edk2-devel] Help with debugging

Andrew Fish via groups.io afish=apple.com at groups.io
Fri Jun 11 20:58:35 UTC 2021



> On Jun 11, 2021, at 1:48 PM, Ethin Probst <harlydavidsen at gmail.com> wrote:
> 
> Okay, so I just tried exactly what you told me to do -- use
> CpuDeadLoop() and then just modify index to get out of it. Here's what
> I do in GDB:
> - Load the EFI application and connect via target remote :1234
> - type `add-symbol-file Build/MdeModule/DEBUG_GCC5/X64/UsbAudio.debug
> 0x0007E4B8000` and answer yes when it prompts me to do so.
> (0x0007E4B8000 is the image base, the entry point is at
> 0x0007E4B9440.)
> - When I try to print the Index symbol, GDB tells me that it isn't in
> the current context.
> I feel like I'm missing something. I'm also not the best with GDB myself. :)

What do you get from the following gdb commands? 
bt
info local
info symbol 0x0007E4B9440

What exactly is gdb showing you?

Thanks,

Andrew Fish

> 
> On 6/11/21, Andrew Fish <afish at apple.com <mailto:afish at apple.com>> wrote:
>> 
>> 
>>> On Jun 11, 2021, at 11:39 AM, Ethin Probst <harlydavidsen at gmail.com>
>>> wrote:
>>> 
>>> Hi Andrew,
>>> How do you debug the EFI binary with LLDB? Can LLDB use GDB stubs or
>>> does that work differently?
>>> 
>> 
>> Ethin,
>> 
>> Lldb is the command line debugger that comes with Xcode on Mac. There is no
>> gdb with Xcode, so I have to use lldb for my day job.
>> 
>> Lldb can speak the gdb remote serial protocol: lldb -o “gdb-remote 9000”
>> That assumes you passed `-gdb tcp::9000`to QEMU.
>> 
>> Thanks,
>> 
>> Andrew Fish
>> 
>>> On 6/11/21, Andrew Fish <afish at apple.com <mailto:afish at apple.com> <mailto:afish at apple.com <mailto:afish at apple.com>>> wrote:
>>>> 
>>>> 
>>>>> On Jun 11, 2021, at 10:06 AM, Ethin Probst <harlydavidsen at gmail.com <mailto:harlydavidsen at gmail.com>>
>>>>> wrote:
>>>>> 
>>>>> Hey all,
>>>>> 
>>>>> So Leif and I have discussed this at length but I thought I'd reach
>>>>> out to all of you for more help.
>>>>> 
>>>>> I'm having a lot of trouble debugging my UEFI app. Here's how I do
>>>>> things:
>>>>> 
>>>>> - I load the app using uefi-run
>>>>> (https://github.com/Richard-W/uefi-run <https://github.com/Richard-W/uefi-run>) like this (from the main EDK
>>>>> II directory): uefi-run -b Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd
>>>>> Build/OvmfX64/DEBUG_GCC5/X64/Shell.efi -- -M q35 -m 24G -usb -device
>>>>> qemu-xhci -device usb-audio,audiodev=audio -audiodev alsa,id=audio -s
>>>>> -debugcon file:../debug.log -global isa-debugcon.iobase=0x402
>>>>> -nographic
>>>>> Or:
>>>>> uefi-run -b Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd
>>>>> Build/OvmfX64/DEBUG_GCC5/X64/Shell.efi -- -M q35 -m 24G -usb -device
>>>>> qemu-xhci -device usb-audio,audiodev=audio -audiodev alsa,id=audio -s
>>>>> -debugcon stdio -global isa-debugcon.iobase=0x402
>>>>> - I connect to the remote GDB stub (localhost:1234) and wait until
>>>>> OVMF gives me the image base. Then I use:
>>>>> add-symbol-file UsbAudio.debug <image base>
>>>>> Here's where everything breaks down. One of two things happens at this
>>>>> point:
>>>>> 1. Either I get the wrong debug information (I get source code but the
>>>>> image isn't loaded anymore), and resetting the system and placing a
>>>>> breakpoint (either software or hardware) has no effect; or
>>>>> 2. If I use CpuBreakpoint(), the firmware gives me the registers and
>>>>> the image base and entry point addresses, and then appears to just sit
>>>>> there waiting for something. Once I load the symbols using the image
>>>>> base it gives me, I can't actually do anything in the debugger; I
>>>>> can't list code because I get "1 in <artificial>", I can't jump into
>>>>> my code without triggering a general protection exception or not
>>>>> actually causing anything to happen... You get the idea.
>>>>> 
>>>>> So I'm really, really confused on what's going wrong. Do you guys have
>>>>> any advice?
>>>> 
>>>> Ethin,
>>>> 
>>>> Caveat emptor as I use lldb for my daily driver debugger so I might be a
>>>> little off on gdb specifics…. Also my terminology may be lldb centric.
>>>> 
>>>> Easy one 1st. When you run on top of a debugger using CpuBreakpoint()
>>>> works
>>>> great as the debugger hides its self from you. On x86 CpuBreakpoint() is
>>>> an
>>>> INT 3h instruction (0xCC) and it causes an exception 3. If you don’t have
>>>> a
>>>> debugger hooked in underneath  the exception 3 is going to get handled
>>>> in
>>>> the unexpected exception handler, and that is probably in the CPUD DXE
>>>> driver or DXE Core or some such. So you are going to end up with the
>>>> PC/IP/RIP in the wrong driver. A lot of times for hardware debuggers it
>>>> works better to use CpuDeadLoop(). The gdb-remote stub from QEMU acts a
>>>> lot
>>>> more like a JTAG hardware debugger than a pure software debugger. Also
>>>> note
>>>> that CpuDeadLoop() is an infinite loop, so you can modify the loop
>>>> variable
>>>> with the debugger to continue.
>>>> 
>>>> I’d suggest a work flow of run your App/Driver, hit the CpuDeadLoop(),
>>>> attach gdb. Now after you have the target established load the symbols.
>>>> The
>>>> reason for me suggesting this flow is the debugger has a flexible concept
>>>> of
>>>> what the target is. If you load symbols that will create a target for a
>>>> stock x86-64 image. When you connect to the QEMU gdb-remote there is a
>>>> handshake that describes the target and what registers are available. I
>>>> seem
>>>> to remember QEMU exports some of the system registers, like the control
>>>> registers, so it is an extended version of the x86-64 target. So this
>>>> changing the target definition might confuse the debugger. To be safe I
>>>> always connect 1st and then load symbols.
>>>> 
>>>> The EFI images are PE/COFF relocatable executables that are linked
>>>> around
>>>> zero. They get loaded into memory and relocated, so that is why you need
>>>> to
>>>> specify the load address to get the symbols to resolve. One trick I use
>>>> is
>>>> to load the ELF (or PE/COFF) build output directly into the debugger.
>>>> This
>>>> lets you poke around the image at the linked address. You can
>>>> disassemble
>>>> the functions to see what they look like, obviously you can read any
>>>> variables. This can be useful if you get the unhandled exception and it
>>>> prints out the load address and offset (you can use the offset directly).
>>>> It
>>>> is also a good way to debug why your symbols are not quite loaded at the
>>>> correct address, as you can see what bytes/instructions should be at a
>>>> given
>>>> address.
>>>> 
>>>> Thanks,
>>>> 
>>>> Andrew Fish
>>>> 
>>>>> 
>>>>> --
>>>>> Signed,
>>>>> Ethin D. Probst
>>>>> 
>>>>> 
>>>>> 
>>>>> 
>>>>> 
>>>> 
>>>> 
>>> 
>>> 
>>> --
>>> Signed,
>>> Ethin D. Probst
>>> 
>>> 
>>> 
>> 
>> 
> 
> 
> -- 
> Signed,
> Ethin D. Probst
> 
> 
> 



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#76408): https://edk2.groups.io/g/devel/message/76408
Mute This Topic: https://groups.io/mt/83473484/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/edk2-devel-archive/attachments/20210611/754392e7/attachment.htm>


More information about the edk2-devel-archive mailing list