Date: Wednesday, May 19, 2021 @ 21:34:27 Author: anatolik Revision: 415775
upgpkg: gdb 10.2-2: FS#70879: apply upstream patch that fixes debugging for 32bit apps Added: gdb/trunk/gdb_dont_overwrite_fs-gs_base_with_-m32.patch Modified: gdb/trunk/PKGBUILD -----------------------------------------------+ PKGBUILD | 14 +- gdb_dont_overwrite_fs-gs_base_with_-m32.patch | 163 ++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 4 deletions(-) Modified: PKGBUILD =================================================================== --- PKGBUILD 2021-05-19 20:57:17 UTC (rev 415774) +++ PKGBUILD 2021-05-19 21:34:27 UTC (rev 415775) @@ -8,7 +8,7 @@ # of gdb (for arm/avr/...) pkgname=(gdb gdb-common) pkgver=10.2 -pkgrel=1 +pkgrel=2 pkgdesc='The GNU Debugger' arch=(x86_64) url='https://www.gnu.org/software/gdb/' @@ -15,16 +15,22 @@ license=(GPL3) makedepends=(glibc gcc-libs texinfo python guile ncurses expat xz mpfr source-highlight readline) -source=(https://ftp.gnu.org/gnu/gdb/${pkgname}-${pkgver}.tar.xz{,.sig}) +source=(https://ftp.gnu.org/gnu/gdb/${pkgname}-${pkgver}.tar.xz{,.sig} + gdb_dont_overwrite_fs-gs_base_with_-m32.patch) + sha1sums=('1056e2743a825ecce46ec9eec37f0b357831012b' - 'SKIP') + 'SKIP' + '7a78c03b563797e5c0ee85a0618a47e4c6677dc4') b2sums=('c5d31d80d2b454767d6f844e8471b012ad437c3872391b618fd7b14c5cf251b78e55d28c12e81382fd600f67e2f618ff5dbe3a7b737a5d5161ceb3542afbb90b' - 'SKIP') + 'SKIP' + '4337167930ecc045b9d19125b975bc98b4b16e05954c45bfa41f0e21471ed7ab5c5a8e9a8479056d7019cd127beed936c664e37d38ee3e99dbe861f8c1a67540') validpgpkeys=('F40ADB902B24264AA42E50BF92EDB04BFF325CF3') # Joel Brobecker prepare() { cd gdb-$pkgver + patch -p1 < ../gdb_dont_overwrite_fs-gs_base_with_-m32.patch # FS#70879 + # hack! - libiberty configure tests for header files using "$CPP $CPPFLAGS" sed -i "/ac_cpp=/s/\$CPPFLAGS/\$CPPFLAGS -O2/" libiberty/configure } Added: gdb_dont_overwrite_fs-gs_base_with_-m32.patch =================================================================== --- gdb_dont_overwrite_fs-gs_base_with_-m32.patch (rev 0) +++ gdb_dont_overwrite_fs-gs_base_with_-m32.patch 2021-05-19 21:34:27 UTC (rev 415775) @@ -0,0 +1,163 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tom de Vries <[email protected]> +Date: Wed, 20 Jan 2021 16:29:30 +0100 +Subject: [PATCH] [gdb/server] Don't overwrite fs/gs_base with -m32 + +Consider a minimal test-case test.c: +... +int main (void) { return 0; } +... +compiled with -m32: +... +$ gcc test.c -m32 +... + +When running the exec using gdbserver on openSUSE Factory (currently running a +linux kernel version 5.10.5): +... +$ gdbserver localhost:12345 a.out +... +to which we connect in a gdb session, we run into a segfault in the inferior: +... +$ gdb -batch -q -ex "target remote localhost:12345" -ex continue +Program received signal SIGSEGV, Segmentation fault. +0xf7dd8bd2 in init_cacheinfo () at ../sysdeps/x86/cacheinfo.c:761 +... + +The segfault is caused by gdbserver overwriting $gs_base with 0 using +PTRACE_SETREGS. After it is overwritten, the next use of $gs in the inferior +will trigger the segfault. + +Before linux kernel version 5.9, the value used by PTRACE_SETREGS for $gs_base +was ignored, but starting version 5.9, the linux kernel has support for +intel architecture extension FSGSBASE, which allows users to modify $gs_base, +and consequently PTRACE_SETREGS can no longer ignore the $gs_base value. + +The overwrite of $gs_base with 0 is done by a memset in x86_fill_gregset, +which was added in commit 9e0aa64f551 "Fix gdbserver qGetTLSAddr for +x86_64 -m32". The memset intends to zero-extend 32-bit registers that are +tracked in the regcache to 64-bit when writing them into the PTRACE_SETREGS +data argument. But in addition, it overwrites other registers that are +not tracked in the regcache, such as $gs_base. + +Fix the segfault by redoing the fix from commit 9e0aa64f551 in minimal form. + +Tested on x86_64-linux: +- openSUSE Leap 15.2 (using kernel version 5.3.18): + - native + - gdbserver -m32 + - -m32 +- openSUSE Factory (using kernel version 5.10.5): + - native + - m32 + +gdbserver/ChangeLog: + +2021-01-20 Tom de Vries <[email protected]> + + * linux-x86-low.cc (collect_register_i386): New function. + (x86_fill_gregset): Remove memset. Use collect_register_i386. + +(cherry picked from commit 037e8112b9794a633248e5aa5943f3be273e0a20) + +Conflicts: + gdbserver/ChangeLog + gdbserver/linux-x86-low.cc +--- + gdbserver/ChangeLog | 5 ++++ + gdbserver/linux-x86-low.cc | 55 +++++++++++++++++++++++--------------- + 2 files changed, 38 insertions(+), 22 deletions(-) + +diff --git a/gdbserver/ChangeLog b/gdbserver/ChangeLog +index 28d0f9bfccb..b87174ce4e3 100644 +--- a/gdbserver/ChangeLog ++++ b/gdbserver/ChangeLog +@@ -1,3 +1,8 @@ ++2021-01-20 Tom de Vries <[email protected]> ++ ++ * linux-x86-low.cc (collect_register_i386): New function. ++ (x86_fill_gregset): Remove memset. Use collect_register_i386. ++ + 2021-01-01 Joel Brobecker <[email protected]> + + * server.cc (gdbserver_version): Update copyright year. +diff --git a/gdbserver/linux-x86-low.cc b/gdbserver/linux-x86-low.cc +index 79284473f14..ea95f3ea2ae 100644 +--- a/gdbserver/linux-x86-low.cc ++++ b/gdbserver/linux-x86-low.cc +@@ -397,6 +397,35 @@ x86_target::low_cannot_fetch_register (int regno) + return regno >= I386_NUM_REGS; + } + ++static void ++collect_register_i386 (struct regcache *regcache, int regno, void *buf) ++{ ++ collect_register (regcache, regno, buf); ++ ++#ifdef __x86_64__ ++ /* In case of x86_64 -m32, collect_register only writes 4 bytes, but the ++ space reserved in buf for the register is 8 bytes. Make sure the entire ++ reserved space is initialized. */ ++ ++ gdb_assert (register_size (regcache->tdesc, regno) == 4); ++ ++ if (regno == RAX) ++ { ++ /* Sign extend EAX value to avoid potential syscall restart ++ problems. ++ ++ See amd64_linux_collect_native_gregset() in ++ gdb/amd64-linux-nat.c for a detailed explanation. */ ++ *(int64_t *) buf = *(int32_t *) buf; ++ } ++ else ++ { ++ /* Zero-extend. */ ++ *(uint64_t *) buf = *(uint32_t *) buf; ++ } ++#endif ++} ++ + static void + x86_fill_gregset (struct regcache *regcache, void *buf) + { +@@ -411,32 +440,14 @@ x86_fill_gregset (struct regcache *regcache, void *buf) + + return; + } +- +- /* 32-bit inferior registers need to be zero-extended. +- Callers would read uninitialized memory otherwise. */ +- memset (buf, 0x00, X86_64_USER_REGS * 8); + #endif + + for (i = 0; i < I386_NUM_REGS; i++) +- collect_register (regcache, i, ((char *) buf) + i386_regmap[i]); +- +- collect_register_by_name (regcache, "orig_eax", +- ((char *) buf) + ORIG_EAX * REGSIZE); ++ collect_register_i386 (regcache, i, ((char *) buf) + i386_regmap[i]); + +-#ifdef __x86_64__ +- /* Sign extend EAX value to avoid potential syscall restart +- problems. +- +- See amd64_linux_collect_native_gregset() in gdb/amd64-linux-nat.c +- for a detailed explanation. */ +- if (register_size (regcache->tdesc, 0) == 4) +- { +- void *ptr = ((gdb_byte *) buf +- + i386_regmap[find_regno (regcache->tdesc, "eax")]); +- +- *(int64_t *) ptr = *(int32_t *) ptr; +- } +-#endif ++ /* Handle ORIG_EAX, which is not in i386_regmap. */ ++ collect_register_i386 (regcache, find_regno (regcache->tdesc, "orig_eax"), ++ ((char *) buf) + ORIG_EAX * REGSIZE); + } + + static void +-- +2.29.2 +
