This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [PATCH] Linux/gdbserver: Correctly handle narrow big-endian register transfers
- From: "Ulrich Weigand" <uweigand at de dot ibm dot com>
- To: macro at mips dot com (Maciej W. Rozycki)
- Cc: gdb-patches at sourceware dot org, arnez at linux dot vnet dot ibm dot com (Andreas Arnez)
- Date: Tue, 22 May 2018 14:26:14 +0200 (CEST)
- Subject: Re: [PATCH] Linux/gdbserver: Correctly handle narrow big-endian register transfers
Maciej W. Rozycki wrote:
> This fixes the problem for MIPS, however from my understanding of your
> commit it will break s390x unless it is further adjusted in a
> target-dependent manner. So my question is: does `ptrace' indeed place
> 32-bit quantities transferred in bits 63:32 of the 64-bit integer data
> quantity passed?
>
> If so, then would wrapping this into `#ifndef __s390x__' be OK with you
> as it's s390x that appears to be an oddball here by representing the
> same 32-bit integer data quantity differently between 32-bit and 64-bit
> systems (i.e. you can't just cast `long' to `int')?
>
> I have no access to an s390x to verify this change. This has passed
> regression testing with o32 and n64 targets with `gdbserver' strapped to
> use PTRACE_PEEKUSR and PTRACE_POKEUSR requests across all registers.
Well, my understanding of PTRACE_PEEKUSR and PTRACE_POKEUSR is that they
are supposed to simulate access to a "user area", i.e. a data structure
that holds per-process status, in word sized chunks. Now of course the
Linux kernel doesn't actually maintain such a "user area", but for the
purpose of those ptrace calls, it is supposed to pretend it does.
So if we e.g. have some word-sized floating-point registers and a halfword
size status register, the kernel would pretend they are stored in a struct
like this:
struct user_area
{
long fpr[16];
int fpc;
};
and if you access this with PTRACE_PEEKUSR at offset
offsetof(struct user_area, fpc)
you get the 8 bytes at this offset. On a big-endian system, those
correspond to getting the 4 bytes of fpc in the most-significant
bytes, and some padding in the least-significant bytes.
This is what gdbserver expects, and what the kernel ptrace logic
(at least on s390x, I cannot say about others) implements:
} else if (addr == (addr_t) &dummy->regs.fp_regs.fpc) {
/*
* floating point control reg. is in the thread structure
*/
tmp = child->thread.fpu.fpc;
tmp <<= BITS_PER_LONG - 32;
If this is implemented differently on mips, I guess gdbserver will
have to handle this, but I don't really like an #ifdef here.
Can't you move the special logic into platform-specific
the_low_target.collect_ptrace_register and
the_low_target.supply_ptrace_register calls instead?
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU/Linux compilers and toolchain
Ulrich.Weigand@de.ibm.com