diff options
-rw-r--r-- | Lessons/Lesson_42/README.md | 181 | ||||
-rw-r--r-- | Lessons/Lesson_42/gdb.png | bin | 0 -> 42170 bytes | |||
-rw-r--r-- | Lessons/Lesson_42/gdb_tui.png | bin | 0 -> 28363 bytes |
3 files changed, 181 insertions, 0 deletions
diff --git a/Lessons/Lesson_42/README.md b/Lessons/Lesson_42/README.md new file mode 100644 index 0000000..f3bb581 --- /dev/null +++ b/Lessons/Lesson_42/README.md @@ -0,0 +1,181 @@ +In this lesson we would talk about how to debug our UEFI application and drivers with GDB. + +To perfrom debug with GDB we need to load debug symbols at the correct offset, for it we need to know: +- app offset in memory +- internal app sections offsets + +# Getting application offset in memory + +Run your QEMU with debug image of OVMF and log functionality enabled: +``` +qemu-system-x86_64 \ + -drive if=pflash,format=raw,readonly,file=Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd \ + -drive format=raw,file=fat:rw:~/UEFI_disk \ + -net none \ + -nographic \ + -global isa-debugcon.iobase=0x402 \ + -debugcon file:debug.log +``` +In a separate terminal window execute: +``` +tail -f debug.log +``` +This way you can follow log runtime. + +Wait for UEFI shell boot and execute our `ShowBootVariables.efi` application. After you do it, something similar to these messages would be produced to `debug.log`: +``` +Loading driver at 0x00006649000 EntryPoint=0x0000664C80F ShowBootVariables.efi +InstallProtocolInterface: BC62157E-3E33-4FEC-9920-2D3B36D750DF 666B898 +ProtectUefiImageCommon - 0x666B4C0 + - 0x0000000006649000 - 0x0000000000005540 +InstallProtocolInterface: 752F3136-4E16-4FDC-A22A-E5F46812F4CA 7EA36C8 +``` + +Right now we are interested in this string: +``` +Loading driver at 0x00006649000 EntryPoint=0x0000664C80F ShowBootVariables.efi +``` +Our image is loaded to `0x6649000`. + +# Getting application sections offset + +Use `objdump` to see what sections are inside `.efi` executable: +``` +$ objdump -h Build/UefiLessonsPkg/DEBUG_GCC5/X64/ShowBootVariables.efi + +Build/UefiLessonsPkg/DEBUG_GCC5/X64/ShowBootVariables.efi: file format pei-x86-64 + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 00004d00 0000000000000240 0000000000000240 00000240 2**4 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .data 00000580 0000000000004f40 0000000000004f40 00004f40 2**4 + CONTENTS, ALLOC, LOAD, DATA + 2 .reloc 00000080 00000000000054c0 00000000000054c0 000054c0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +``` +And what sections are inside `.debug` version: +``` +$ objdump -h Build/UefiLessonsPkg/DEBUG_GCC5/X64/ShowBootVariables.debug + +Build/UefiLessonsPkg/DEBUG_GCC5/X64/ShowBootVariables.debug: file format elf64-x86-64 + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 00004cf5 0000000000000240 0000000000000240 000000c0 2**6 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .data 000004a1 0000000000004f40 0000000000004f40 00004dc0 2**6 + CONTENTS, ALLOC, LOAD, RELOC, DATA + 2 .eh_frame 00000000 0000000000005400 0000000000005400 00005280 2**3 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 3 .rela 00000510 0000000000005400 0000000000005400 00005280 2**3 + CONTENTS, READONLY + 4 .build-id 00000024 0000000000005910 0000000000005910 00005790 2**2 + CONTENTS, READONLY + 5 .debug_info 000283a4 0000000000000000 0000000000000000 000057b4 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING, OCTETS + 6 .debug_abbrev 00003635 0000000000000000 0000000000000000 0002db58 2**0 + CONTENTS, READONLY, DEBUGGING, OCTETS + 7 .debug_loc 00009fc9 0000000000000000 0000000000000000 0003118d 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING, OCTETS + 8 .debug_aranges 00000570 0000000000000000 0000000000000000 0003b156 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING, OCTETS + 9 .debug_ranges 000013f0 0000000000000000 0000000000000000 0003b6c6 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING, OCTETS + 10 .debug_line 00007a5b 0000000000000000 0000000000000000 0003cab6 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING, OCTETS + 11 .debug_str 000069e4 0000000000000000 0000000000000000 00044511 2**0 + CONTENTS, READONLY, DEBUGGING, OCTETS + 12 .debug_frame 000015a8 0000000000000000 0000000000000000 0004aef8 2**3 + CONTENTS, RELOC, READONLY, DEBUGGING, OCTETS +``` +As you can see `*.efi` file is a version without any `.debug*` sections. + +Right now we are interested in `File off` column of the image that is getting executed - `ShowBootVariables.efi`. + +- `.text` section has offset `0x240` +- `.data` section has offset `0x4f40` + +# Loading debug symbols to GDB + +First of all, to make remote debugging possible we have to provide `-s` parameter for QEMU. This is a shorthand for `tcp::1234`. QEMU will listen for GDB connections on this port. +``` +qemu-system-x86_64 \ + -drive if=pflash,format=raw,readonly,file=Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd \ + -drive format=raw,file=fat:rw:~/UEFI_disk \ + -net none \ + -nographic \ + -global isa-debugcon.iobase=0x402 \ + -debugcon file:debug.log \ + -s +``` + +Now we need to calculate addresses for `.text` and `.data` sections: +``` +0x6649000 + 0x240 = 0x6649240 +0x6649000 + 0x4f40 = 0x664df40 +``` + +Run GDB and load symbols into it: +``` +$ gdb +(gdb) add-symbol-file Build/UefiLessonsPkg/DEBUG_GCC5/X64/ShowBootVariables.debug 0x6649240 -s .data 0x664df40 +add symbol table from file "Build/UefiLessonsPkg/DEBUG_GCC5/X64/ShowBootVariables.debug" at + .text_addr = 0x6649240 + .data_addr = 0x664df40 +(y or n) y +Reading symbols from Build/UefiLessonsPkg/DEBUG_GCC5/X64/ShowBootVariables.debug... +``` + +The entry point of our application is `ShellAppMain` function. In a separate terminal find the string in a file where it is defined: +``` +$ grep -n ShellAppMain UefiLessonsPkg/ShowBootVariables/ShowBootVariables.c +67:INTN EFIAPI ShellAppMain(IN UINTN Argc, IN CHAR16 **Argv) +``` + +Set breakpint at that place: +``` +(gdb) b UefiLessonsPkg/ShowBootVariables/ShowBootVariables.c:67 +Breakpoint 1 at 0x664c50f: file /home/kostr/tiano/edk2/UefiLessonsPkg/ShowBootVariables/ShowBootVariables.c, line 68. +``` + +Connect to the remote: +``` +(gdb) target remote :1234 +Remote debugging using :1234 +warning: No executable has been specified and target does not support +determining executable automatically. Try using the "file" command. +0x000000000717d841 in ?? () +``` + +This will stop QEMU, so we need to execute `c` (=continue) to make QEMU interactive again: +``` +(gdb) c +Continuing. +``` +Now GDB is waiting for a breakpoint hit. + +Swith to QEMU terminal and run our app +``` +FS0:\> ShowBootVariables.efi +``` +On GDB you should receive a breakpoint hit: +``` +Breakpoint 1, ShellAppMain (Argc=1, Argv=0x666a398) at /home/kostr/tiano/edk2/UefiLessonsPkg/ShowBootVariables/ShowBootVariables.c:73 +73 Status = GetNvramVariable(L"BootCurrent", &gEfiGlobalVariableGuid, (VOID**)&BootCurrent, &OptionSize); +(gdb) +``` + +![gdb](gdb.png?raw=true "gdb") + +To ease GDB development I suggest you to try TUI mode (https://sourceware.org/gdb/onlinedocs/gdb/TUI.html): +``` +(gdb) tui enable +``` +In this mode source code file would be displayed right above the GDB prompt. + +![gdb_tui](gdb_tui.png?raw=true "gdb_tui") + + + + diff --git a/Lessons/Lesson_42/gdb.png b/Lessons/Lesson_42/gdb.png Binary files differnew file mode 100644 index 0000000..90e5da9 --- /dev/null +++ b/Lessons/Lesson_42/gdb.png diff --git a/Lessons/Lesson_42/gdb_tui.png b/Lessons/Lesson_42/gdb_tui.png Binary files differnew file mode 100644 index 0000000..28fa230 --- /dev/null +++ b/Lessons/Lesson_42/gdb_tui.png |