mirror of
https://github.com/Motorhead1991/qemu.git
synced 2026-01-06 06:27:41 -07:00
When debugging qemu-user processes using gdbstub, the following warning
appears every time:
warning: BFD: warning: system-supplied DSO at 0x7f8253cc3000 has a corrupt string table index
The reason is that QEMU does not map the VDSO's section headers. The
VDSO's ELF header's e_shoff points to zeros, which GDB fails to parse.
The difference with the kernel's VDSO is that the latter is mapped as a
blob, ignoring program headers - which also don't cover the section
table. QEMU, on the other hand, loads it as an ELF file.
There appears to be no way to place section headers inside a section,
and, therefore, no way to refer to them from a linker script. Also, ld
hardcodes section headers to be non-loadable, see
_bfd_elf_assign_file_positions_for_non_load(). In theory ld could be
enhanced by implementing an "SHDRS" keyword in addition to the existing
"FILEHDR" and "PHDRS".
There are multiple ways to resolve the issue:
- Copy VDSO as a blob in load_elf_vdso(). This would require creating
specialized loader logic, that duplicates parts of load_elf_image().
- Fix up VDSO's PHDR size in load_elf_vdso(). This would require either
duplicating the parsing logic, or adding an ugly parameter to
load_elf_image().
- Fix up VDSO's PHDR size in gen-vdso. This is the simplest solution,
so do it.
There are two tricky parts:
- Byte-swaps need to be done either on local copies, or in-place and
then reverted in the end. To preserve the existing code structure, do
the former for Sym and Dyn, and the latter for Ehdr, Phdr, and Shdr.
- There must be no .bss, which is already the case - but having an
explicit check is helpful to ensure correctness.
To verify this change, I diffed the on-disk and the loaded VDSOs; the
result does not show anything unusual, except for what seems to be an
existing oversight (which should probably be fixed separately):
│ Symbol table '.dynsym' contains 8 entries:
│ Num: Value Size Type Bind Vis Ndx Name
│ - 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
│ - 6: 0000000000000000 0 OBJECT GLOBAL DEFAULT ABS LINUX_2.6.29
│ + 0: 00007f61075bf000 0 NOTYPE LOCAL DEFAULT UND
│ + 6: 00007f61075bf000 0 OBJECT GLOBAL DEFAULT ABS LINUX_2.6.29
Fixes:
|
||
|---|---|---|
| .. | ||
| aarch64 | ||
| alpha | ||
| arm | ||
| generic | ||
| hexagon | ||
| hppa | ||
| i386 | ||
| include | ||
| loongarch64 | ||
| m68k | ||
| microblaze | ||
| mips | ||
| mips64 | ||
| openrisc | ||
| ppc | ||
| riscv | ||
| s390x | ||
| sh4 | ||
| sparc | ||
| x86_64 | ||
| xtensa | ||
| cpu_loop-common.h | ||
| elfload.c | ||
| errnos.c.inc | ||
| exit.c | ||
| fd-trans.c | ||
| fd-trans.h | ||
| flat.h | ||
| flatload.c | ||
| gen-vdso-elfn.c.inc | ||
| gen-vdso.c | ||
| ioctls.h | ||
| linux_loop.h | ||
| linuxload.c | ||
| loader.h | ||
| main.c | ||
| meson.build | ||
| mmap.c | ||
| qemu.h | ||
| semihost.c | ||
| signal-common.h | ||
| signal.c | ||
| socket.h | ||
| strace.c | ||
| strace.h | ||
| strace.list | ||
| syscall.c | ||
| syscall_defs.h | ||
| syscall_types.h | ||
| thunk.c | ||
| trace-events | ||
| trace.h | ||
| uaccess.c | ||
| uname.c | ||
| uname.h | ||
| user-internals.h | ||
| user-mmap.h | ||
| vm86.c | ||