Hi Andrew, How do you debug the EFI binary with LLDB? Can LLDB use GDB stubs or does that work differently?
On 6/11/21, Andrew Fish <af...@apple.com> wrote: > > >> On Jun 11, 2021, at 10:06 AM, Ethin Probst <harlydavid...@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) 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 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#76405): https://edk2.groups.io/g/devel/message/76405 Mute This Topic: https://groups.io/mt/83473484/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-