Page MenuHomeFreeBSD

Make kernel's note segment to be loaded so that debugger can match with coredump
AbandonedPublic

Authored by aokblast on Feb 6 2024, 2:05 AM.
Tags
None
Referenced Files
Unknown Object (File)
Sat, Apr 27, 7:52 AM
Unknown Object (File)
Sat, Apr 27, 7:52 AM
Unknown Object (File)
Sat, Apr 27, 6:15 AM
Unknown Object (File)
Fri, Apr 26, 3:18 AM
Unknown Object (File)
Apr 18 2024, 4:05 PM
Unknown Object (File)
Mar 25 2024, 8:09 PM
Unknown Object (File)
Feb 14 2024, 3:40 AM
Unknown Object (File)
Feb 9 2024, 11:00 PM
Subscribers

Details

Summary

This patch load PT_NOTE section in to memory so the debugger can compare the kernel with corresponding coredump. WIth this patch, debugger can prevent developer falsely load the kernel with unmatched coredump. As the note section is as small as 448 bytes in my build. I think it is a reasonable tradeoff.

I have send a corresponding PR in LLDB.

There is an example about this patch:

sudo lldb -O "log enable lldb dyld" /boot/kernel.old/kernel --core /dev/mem

Result:

(lldb) target create "/boot/kernel.old/kernel" --core "/dev/mem"
lldb             DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress: looking for kernel binary at 0xffffffff80200000
lldb             DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress Cannot match coredump with binary by build-id
Core file '/dev/mem' (x86_64) was loaded.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 55821
Build 52710: arc lint + arc unit

Event Timeline

aokblast added reviewers: lwhsu, emaste.

So why not embed the PT_NOTE into the kernel text segment using ldscript? IMO it is more reliable.

stand/common/load_elf.c
643

Style for the comment is wrong.

In D43757#1004795, @kib wrote:

So why not embed the PT_NOTE into the kernel text segment using ldscript? IMO it is more reliable.

We probably want to combine it with the segment holding .rodata?

Does it works? Because the section name can only appear once in a ldscript. So if we move the .note.gnu.build-id section into rodata, it will cause the ELF cannot find this section and finally PT_NOTE segment will not contains .note.gnu.build-id. Besides, without this section, we cannot get the build-id hash data from section VMA as the most debugger expected.

I have done some experiment by modifying the ldscript as following:

.rodata         :
  {
    *(.rodata .rodata.* .gnu.linkonce.r.*)
    PROVIDE (__build_id_start = .);
    *(.note.gnu.build-id)
    PROVIDE (__build_id_end = .);
  }

And after compilation:

Elf file type is EXEC (Executable file)
Entry point 0xffffffff80380000
There are 11 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0xffffffff80200040 0x0000000000200040
                 0x0000000000000268 0x0000000000000268  R      0x8
  INTERP         0x00000000000002a8 0xffffffff802002a8 0x00000000002002a8
                 0x000000000000000d 0x000000000000000d  R      0x1
      [Requesting program interpreter: /red/herring]
  LOAD           0x0000000000000000 0xffffffff80200000 0x0000000000200000
                 0x000000000017f1b8 0x000000000017f1b8  R      0x200000
  LOAD           0x000000000017f1c0 0xffffffff8037f1c0 0x000000000037f1c0
                 0x0000000000d8f708 0x0000000000d8f708  R E    0x200000
  LOAD           0x0000000000f0e8d0 0xffffffff8110e8d0 0x000000000110e8d0
                 0x000000000042b365 0x000000000042b365  R      0x200000
  LOAD           0x0000000001400000 0xffffffff81600000 0x0000000001600000
                 0x0000000000000180 0x0000000000000180  RW     0x200000
  LOAD           0x0000000001401000 0xffffffff81601000 0x0000000001601000
                 0x000000000018e5b0 0x00000000005ff000  RW     0x200000
  DYNAMIC        0x0000000001400000 0xffffffff81600000 0x0000000001600000
                 0x0000000000000180 0x0000000000000180  RW     0x8
  GNU_RELRO      0x0000000001400000 0xffffffff81600000 0x0000000001600000
                 0x0000000000000180 0x0000000000001000  R      0x1
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x0
  NOTE           0x00000000000002b8 0xffffffff802002b8 0x00000000002002b8
                 0x000000000000019c 0x000000000000019c  R      0x4

 Section to Segment mapping:
  Segment Sections...
   00
   01     .interp
   02     .interp .note.Xen .hash .gnu.hash .dynsym .dynstr .rela.plt .rela.dyn
   03     .plt .text
   04     .rodata .eh_frame set_sysctl_set set_modmetadata_set set_cam_xpt_xport_set set_cam_xpt_proto_set set_kdb_dbbe_set set_ah_chips set_ah_rfs set_kbddriver_set set_sdt_providers_set set_sdt_probes_set set_sdt_argtypes_set set_scterm_set set_cons_set set_gdb_dbgport_set set_uart_acpi_class_and_device_set usb_host_id set_vt_drv_set set_elf64_regset set_elf32_regset set_compressors set_ratectl_set set_crypto_set set_ieee80211_ioctl_getset set_ieee80211_ioctl_setset set_scanner_set set_videodriver_set set_scrndr_set set_vga_set kern_conf
   05     .dynamic
   06     .got.plt .data.read_frequently .data.read_mostly .data.exclusive_cache_line .data set_sysinit_set set_sysuninit_set set_pcpu set_vnet .bss
   07     .dynamic
   08     .dynamic
   09
   10     .note.Xen

Combine != move into, and segments != sections.

I believe the build_id note is already in the RO segment:

Elf file type is EXEC (Executable file)
Entry point 0xffffffff8037f000
There are 11 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flg    Align
  PHDR           0x0000000000000040 0xffffffff80200040 0x0000000000200040
                 0x0000000000000268 0x0000000000000268  R      0x8
  INTERP         0x00000000000002a8 0xffffffff802002a8 0x00000000002002a8
                 0x000000000000000d 0x000000000000000d  R      0x1
      [Requesting program interpreter: /red/herring]
  LOAD           0x0000000000000000 0xffffffff80200000 0x0000000000200000
                 0x000000000017e5d8 0x000000000017e5d8  R      0x200000
  LOAD           0x000000000017e5e0 0xffffffff8037e5e0 0x000000000037e5e0
                 0x0000000000d87648 0x0000000000d87648  R E    0x200000
  LOAD           0x0000000000f05c30 0xffffffff81105c30 0x0000000001105c30
                 0x0000000000429bfc 0x0000000000429bfc  R      0x200000
  LOAD           0x0000000001400000 0xffffffff81600000 0x0000000001600000
                 0x0000000000000180 0x0000000000000180  RW     0x200000
  LOAD           0x0000000001401000 0xffffffff81601000 0x0000000001601000
                 0x000000000018d530 0x00000000005ff000  RW     0x200000
  DYNAMIC        0x0000000001400000 0xffffffff81600000 0x0000000001600000
                 0x0000000000000180 0x0000000000000180  RW     0x8
  GNU_RELRO      0x0000000001400000 0xffffffff81600000 0x0000000001600000
                 0x0000000000000180 0x0000000000000180  R      0x1
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0
  NOTE           0x000000000132f5d4 0xffffffff8152f5d4 0x000000000152f5d4
                 0x00000000000001c0 0x00000000000001c0  R      0x4

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .interp .hash .gnu.hash .dynsym .dynstr .rela.plt .rela.dyn 
   03     .plt .text 
   04     .rodata set_sysctl_set set_modmetadata_set set_cam_xpt_xport_set set_cam_xpt_proto_set set_kdb_dbbe_set set_ah_chips set_ah_rfs set_kbddriver_set set_sdt_providers_set set_sdt_probes_set set_sdt_argtypes_set set_scterm_set set_cons_set set_gdb_dbgport_set set_uart_class_set set_uart_acpi_class_and_device_set usb_host_id set_vt_drv_set set_elf64_regset set_elf32_regset set_compressors set_ratectl_set set_crypto_set set_ieee80211_ioctl_getset set_ieee80211_ioctl_setset set_scanner_set set_videodriver_set set_scrndr_set set_vga_set kern_conf .note.gnu.build-id .note.Xen .eh_frame 
   05     .dynamic 
   06     .got.plt .data.read_frequently .data.read_mostly .data.exclusive_cache_line .data set_sysinit_set set_sysuninit_set set_pcpu set_vnet .bss 
   07     .dynamic 
   08     .dynamic 
   09     
   10     .note.gnu.build-id .note.Xen

In particular, the PT_NOTE segment lies within segment 4 (0xffffffff81105c30-0xffffffff8152f82c). There is only one copy of the build_id note.

I will ask you again in AsiaBSDCon personally because I found something strange on my experiment. Thanks your guys help!

I think MarkJ is right and then we can abandon this patch and just let the LLDB guys merge the patch into LLDB.