gdbsymbolselfdebug-symbols

gdb shows ELF section names also when the executable file is not accessible


On my Linux system, gdb shows names of the sections within the debugged ELF executable also when the ELF executable file itself is not accessible from gdb since it exists within a filesystem mounted on a different mount namespace.

root@host:/# gdb -q attach 7173
attach: No such file or directory.
Attaching to process 7173
[New LWP 17381]
[New LWP 17380]
[New LWP 17379]
[New LWP 17378]
[New LWP 9639]
[New LWP 9618]
[New LWP 9617]
[New LWP 7533]
[New LWP 7531]
[New LWP 7530]
[New LWP 7529]
[New LWP 7323]
[New LWP 7297]
[New LWP 7291]
[New LWP 7290]
[New LWP 7285]
[New LWP 7284]
(gdb) info files 
Symbols from "target:/proc/7173/exe".
Native process:
        Using the running image of attached process 7173.
        While running this, GDB does not access memory from...
Local exec file:
        `target:/proc/7173/exe', file type elf64-x86-64.
        Entry point: 0x564521600970
        0x00005645215fa200 - 0x00005645215fa21c is .interp
        0x00005645215fa21c - 0x00005645215fa23c is .note.ABI-tag
        0x00005645215fa23c - 0x00005645215fa260 is .note.gnu.build-id
        0x00005645215fa260 - 0x00005645215fb0b8 is .dynsym
        0x00005645215fb0b8 - 0x00005645215fb1ea is .gnu.version
        0x00005645215fb1ec - 0x00005645215fb23c is .gnu.version_r
        0x00005645215fb240 - 0x00005645215fb588 is .gnu.hash
        0x00005645215fb588 - 0x00005645215fcc2c is .dynstr
        0x00005645215fcc30 - 0x00005645215fe850 is .rela.dyn
        0x00005645215fe850 - 0x00005645215feaf0 is .rela.plt
        0x00005645215feaf0 - 0x00005645215fff41 is .rodata
        0x00005645215fff44 - 0x0000564521600140 is .eh_frame_hdr
        0x0000564521600140 - 0x000056452160096c is .eh_frame
        0x0000564521600970 - 0x00005645216012f1 is .text
        0x00005645216012f4 - 0x000056452160130e is .init
        0x0000564521601310 - 0x0000564521601319 is .fini
        0x0000564521601320 - 0x00005645216014f0 is .plt
        0x0000564521602000 - 0x0000564521602010 is .data
        0x0000564521602010 - 0x0000564521602018 is .jcr
        0x0000564521602018 - 0x0000564521602018 is .tm_clone_table
        0x0000564521602018 - 0x0000564521602020 is .fini_array
        0x0000564521602020 - 0x0000564521602028 is .init_array
        0x0000564521602028 - 0x0000564521602fe8 is .data.rel.ro
        0x0000564521602fe8 - 0x0000564521603298 is .dynamic
        0x0000564521603298 - 0x00005645216034e0 is .got
        0x00005645216034e0 - 0x00005645216035d8 is .got.plt
        0x00005645216035e0 - 0x0000564521603ee4 is .bss
        0x00007f0bfa9e4190 - 0x00007f0bfa9e41b4 is .note.gnu.build-id in target:/pkg/lib/libmemdbg.so
        0x00007f0bfa9e41b8 - 0x00007f0bfa9e467c is .hash in target:/pkg/lib/libmemdbg.so
        0x00007f0bfa9e4680 - 0x00007f0bfa9e56a0 is .dynsym in target:/pkg/lib/libmemdbg.so
        0x00007f0bfa9e56a0 - 0x00007f0bfa9e60d1 is .dynstr in target:/pkg/lib/libmemdbg.so
        0x00007f0bfa9e60d2 - 0x00007f0bfa9e622a is .gnu.version in target:/pkg/lib/libmemdbg.so
        0x00007f0bfa9e6230 - 0x00007f0bfa9e62d0 is .gnu.version_r in target:/pkg/lib/libmemdbg.so
        0x00007f0bfa9e62d0 - 0x00007f0bfa9e6690 is .rela.dyn in target:/pkg/lib/libmemdbg.so
--Type <RET> for more, q to quit, c to continue without paging--q
Quit
(gdb) 

Af far as I can understand, gdb is actually reading those infos about ELF executable sections directly from process's memory image.

However the point is: since ELF section header table (SHT) isn't loaded in process's memory address space, how does gdb get the names of those ELF executable's sections ? Thanks.

Edited to add infos based on comment received: even using gdb -q -p 7173, I see exactly the same ELF executable's sections referenced. Why gdb is still able to get those infos about sections supposed it has no access to the ELF executable file?

root@host:/# gdb -q -p 7173
Attaching to process 7173
[New LWP 17381]
[New LWP 17380]
[New LWP 17379]
<snip....>
[New LWP 7351]
[New LWP 7323]
[New LWP 7297]
[New LWP 7291]
[New LWP 7290]
[New LWP 7285]
[New LWP 7284]

warning: Expected absolute pathname for libpthread in the inferior, but got target:/lib64/libpthread.so.0.

warning: Unable to find libthread_db matching inferior's thread library, thread debugging will not be available.
0x00007f0bf997ac73 in epoll_wait () at ../sysdeps/unix/syscall-template.S:81

warning: 81     ../sysdeps/unix/syscall-template.S: No such file or directory
(gdb) info files 
Symbols from "target:/proc/7173/exe".
Native process:
        Using the running image of attached process 7173.
        While running this, GDB does not access memory from...
Local exec file:
        `target:/proc/7173/exe', file type elf64-x86-64.
        Entry point: 0x564521600970
        0x00005645215fa200 - 0x00005645215fa21c is .interp
        0x00005645215fa21c - 0x00005645215fa23c is .note.ABI-tag
        0x00005645215fa23c - 0x00005645215fa260 is .note.gnu.build-id
        0x00005645215fa260 - 0x00005645215fb0b8 is .dynsym
        0x00005645215fb0b8 - 0x00005645215fb1ea is .gnu.version
        0x00005645215fb1ec - 0x00005645215fb23c is .gnu.version_r
        0x00005645215fb240 - 0x00005645215fb588 is .gnu.hash
        0x00005645215fb588 - 0x00005645215fcc2c is .dynstr
        0x00005645215fcc30 - 0x00005645215fe850 is .rela.dyn
        0x00005645215fe850 - 0x00005645215feaf0 is .rela.plt
        0x00005645215feaf0 - 0x00005645215fff41 is .rodata
        0x00005645215fff44 - 0x0000564521600140 is .eh_frame_hdr
        0x0000564521600140 - 0x000056452160096c is .eh_frame
        0x0000564521600970 - 0x00005645216012f1 is .text
        0x00005645216012f4 - 0x000056452160130e is .init
        0x0000564521601310 - 0x0000564521601319 is .fini
        0x0000564521601320 - 0x00005645216014f0 is .plt
        0x0000564521602000 - 0x0000564521602010 is .data
        0x0000564521602010 - 0x0000564521602018 is .jcr
        0x0000564521602018 - 0x0000564521602018 is .tm_clone_table
        0x0000564521602018 - 0x0000564521602020 is .fini_array
        0x0000564521602020 - 0x0000564521602028 is .init_array
        0x0000564521602028 - 0x0000564521602fe8 is .data.rel.ro
        0x0000564521602fe8 - 0x0000564521603298 is .dynamic
        0x0000564521603298 - 0x00005645216034e0 is .got
        0x00005645216034e0 - 0x00005645216035d8 is .got.plt
        0x00005645216035e0 - 0x0000564521603ee4 is .bss
        0x00007f0bfa9e4190 - 0x00007f0bfa9e41b4 is .note.gnu.build-id in target:/pkg/lib/libmemdbg.so
        0x00007f0bfa9e41b8 - 0x00007f0bfa9e467c is .hash in target:/pkg/lib/libmemdbg.so
        0x00007f0bfa9e4680 - 0x00007f0bfa9e56a0 is .dynsym in target:/pkg/lib/libmemdbg.so
        0x00007f0bfa9e56a0 - 0x00007f0bfa9e60d1 is .dynstr in target:/pkg/lib/libmemdbg.so
        0x00007f0bfa9e60d2 - 0x00007f0bfa9e622a is .gnu.version in target:/pkg/lib/libmemdbg.so
        0x00007f0bfa9e6230 - 0x00007f0bfa9e62d0 is .gnu.version_r in target:/pkg/lib/libmemdbg.so
        0x00007f0bfa9e62d0 - 0x00007f0bfa9e6690 is .rela.dyn in target:/pkg/lib/libmemdbg.so
--Type <RET> for more, q to quit, c to continue without paging--q
Quit
(gdb)

Solution

  • Since version 7.10, when attaching to a process in a different mount namespace, GDB will fork off a helper process, and the helper process will then use setns to associate itself with the required namespace. GDB then communicates with this helper process via a socket. In this way GDB is able to read files from the alternative namespace.

    As far as I can tell this isn't documented anywhere in the GDB manual, it "just works", though it was mentioned in the NEWS file.