> On Jun 11, 2021, at 11:39 AM, Ethin Probst <harlydavid...@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 <af...@apple.com <mailto: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 (#76406): https://edk2.groups.io/g/devel/message/76406 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] -=-=-=-=-=-=-=-=-=-=-=-