Re: support biarch gcore?

Mark Kettenis
2010-07-05T11:55:13Z

> Date: Mon, 5 Jul 2010 09:12:35 +0200
> From: Jan Kratochvil <jan.kratochvil@redhat.com>
>
> On Mon, 05 Jul 2010 06:52:37 +0200, Jon Zhou wrote:
> > Regarding this case, does the current release solve it ? I just tried the
> > patch but looks it doesn't work
>
> Issue is tracked at:
> amd64 gdb generates corrupted 32bit core file
> http://sourceware.org/bugzilla/show_bug.cgi?id=11467
>
> There was a patchset by H.J.Lu but it did not make it in FSF GDB:
> PATCH: PR corefiles/11467: amd64 gdb generates corrupted 32bit core file
> http://sourceware.org/ml/gdb-patches/2010-04/msg00315.html
> with the last mail of this thread:
> http://sourceware.org/ml/gdb-patches/2010-04/msg00427.html
> > Please stop sending diffs until you understand how the code is
> > supposed to work.
>
> The Fedora patch
> http://cvs.fedoraproject.org/viewvc/rpms/gdb/devel/gdb-6.5-gcore-i386-on-amd64.patch?content-type=text%2Fplain&view=co
>
> will be rebased or replaced by H.J.Lu's one for gdb-7.2-pre by 2010-07-27.

The proper way to fix the issue is to add proper cross-core support to
BFD for i386 and amd64 like was done for powerpc/powerpc64 a couple of
years ago. See the thread starting at:

http://sourceware.org/ml/binutils/2010-04/msg00225.html

Perhaps I need to resubmit that diff now that things have settled down
a bit.

With that diff in, there still is a GDB issue that needs to be
resolved. The core generation code in
linux-nat.c:linux_nat_do_thread_registers() allocates a buffer of type
gdb_gregset_t to store the registers. Since its size differs between
i386 and amd64 the size passed to _reget_from_core_section() is always
the size of the amd64 gdb_gregset_t. Since the current code checks
for an exact match, it fails to return a regset, and things go
downhill from there.

Fixing the code in linux-nat.c is a bit nasty:

* The definition of the 32-bit version of gdb_gregset_t isn't readily
available on 64-bit systems.

* The code is used on all Linux platforms and only a few of them are
bi-arch.

An alternative solution would be to make _regset_from_core_section() a
little bit more forgiving. The diff below works since the size of the
amd64 gdb_gregset_t is larger than the i386-version.

2010-07-05 Mark Kettenis <kettenis@gnu.org>

* i386-tdep.c (i386_supply_gregset, i386_collect_gregset)
(i386_regset_from_core_section): Relax check for size of .reg
section.

Index: i386-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-tdep.c,v
retrieving revision 1.316
diff -u -p -r1.316 i386-tdep.c
--- i386-tdep.c 22 Jun 2010 02:15:45 -0000 1.316
+++ i386-tdep.c 5 Jul 2010 11:50:55 -0000
@@ -2775,7 +2775,7 @@ i386_supply_gregset (const struct regset
const gdb_byte *regs = gregs;
int i;

- gdb_assert (len == tdep->sizeof_gregset);
+ gdb_assert (len >= tdep->sizeof_gregset);

for (i = 0; i < tdep->gregset_num_regs; i++)
{
@@ -2799,7 +2799,7 @@ i386_collect_gregset (const struct regse
gdb_byte *regs = gregs;
int i;

- gdb_assert (len == tdep->sizeof_gregset);
+ gdb_assert (len >= tdep->sizeof_gregset);

for (i = 0; i < tdep->gregset_num_regs; i++)
{
@@ -2880,7 +2880,7 @@ i386_regset_from_core_section (struct gd
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

- if (strcmp (sect_name, ".reg") == 0 && sect_size == tdep->sizeof_gregset)
+ if (strcmp (sect_name, ".reg") == 0 && sect_size >= tdep->sizeof_gregset)
{
if (tdep->gregset == NULL)
tdep->gregset = regset_alloc (gdbarch, i386_supply_gregset,