|
Packit Service |
97d2fb |
/* Fetch live process registers from TID.
|
|
Packit Service |
97d2fb |
Copyright (C) 2013 Red Hat, Inc.
|
|
Packit Service |
97d2fb |
This file is part of elfutils.
|
|
Packit Service |
97d2fb |
|
|
Packit Service |
97d2fb |
This file is free software; you can redistribute it and/or modify
|
|
Packit Service |
97d2fb |
it under the terms of either
|
|
Packit Service |
97d2fb |
|
|
Packit Service |
97d2fb |
* the GNU Lesser General Public License as published by the Free
|
|
Packit Service |
97d2fb |
Software Foundation; either version 3 of the License, or (at
|
|
Packit Service |
97d2fb |
your option) any later version
|
|
Packit Service |
97d2fb |
|
|
Packit Service |
97d2fb |
or
|
|
Packit Service |
97d2fb |
|
|
Packit Service |
97d2fb |
* the GNU General Public License as published by the Free
|
|
Packit Service |
97d2fb |
Software Foundation; either version 2 of the License, or (at
|
|
Packit Service |
97d2fb |
your option) any later version
|
|
Packit Service |
97d2fb |
|
|
Packit Service |
97d2fb |
or both in parallel, as here.
|
|
Packit Service |
97d2fb |
|
|
Packit Service |
97d2fb |
elfutils is distributed in the hope that it will be useful, but
|
|
Packit Service |
97d2fb |
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
97d2fb |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
97d2fb |
General Public License for more details.
|
|
Packit Service |
97d2fb |
|
|
Packit Service |
97d2fb |
You should have received copies of the GNU General Public License and
|
|
Packit Service |
97d2fb |
the GNU Lesser General Public License along with this program. If
|
|
Packit Service |
97d2fb |
not, see <http://www.gnu.org/licenses/>. */
|
|
Packit Service |
97d2fb |
|
|
Packit Service |
97d2fb |
#ifdef HAVE_CONFIG_H
|
|
Packit Service |
97d2fb |
# include <config.h>
|
|
Packit Service |
97d2fb |
#endif
|
|
Packit Service |
97d2fb |
|
|
Packit Service |
97d2fb |
#include "system.h"
|
|
Packit Service |
97d2fb |
#include <assert.h>
|
|
Packit Service |
97d2fb |
#if defined(__s390__) && defined(__linux__)
|
|
Packit Service |
97d2fb |
# include <sys/user.h>
|
|
Packit Service |
97d2fb |
# include <sys/ptrace.h>
|
|
Packit Service |
97d2fb |
# include <asm/ptrace.h>
|
|
Packit Service |
97d2fb |
#endif
|
|
Packit Service |
97d2fb |
|
|
Packit Service |
97d2fb |
#define BACKEND s390_
|
|
Packit Service |
97d2fb |
#include "libebl_CPU.h"
|
|
Packit Service |
97d2fb |
|
|
Packit Service |
97d2fb |
bool
|
|
Packit Service |
97d2fb |
s390_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
|
|
Packit Service |
97d2fb |
ebl_tid_registers_t *setfunc __attribute__ ((unused)),
|
|
Packit Service |
97d2fb |
void *arg __attribute__ ((unused)))
|
|
Packit Service |
97d2fb |
{
|
|
Packit Service |
97d2fb |
#if !defined(__s390__) || !defined(__linux__)
|
|
Packit Service |
97d2fb |
return false;
|
|
Packit Service |
97d2fb |
#else /* __s390__ */
|
|
Packit Service |
97d2fb |
struct user user_regs;
|
|
Packit Service |
97d2fb |
ptrace_area parea;
|
|
Packit Service |
97d2fb |
parea.process_addr = (uintptr_t) &user_regs;
|
|
Packit Service |
97d2fb |
parea.kernel_addr = 0;
|
|
Packit Service |
97d2fb |
parea.len = sizeof (user_regs);
|
|
Packit Service |
97d2fb |
if (ptrace (PTRACE_PEEKUSR_AREA, tid, &parea, NULL) != 0)
|
|
Packit Service |
97d2fb |
return false;
|
|
Packit Service |
97d2fb |
/* If we run as s390x we get the 64-bit registers of tid.
|
|
Packit Service |
97d2fb |
But -m31 executable seems to use only the 32-bit parts of its
|
|
Packit Service |
97d2fb |
registers so we ignore the upper half. */
|
|
Packit Service |
97d2fb |
Dwarf_Word dwarf_regs[16];
|
|
Packit Service |
97d2fb |
for (unsigned u = 0; u < 16; u++)
|
|
Packit Service |
97d2fb |
dwarf_regs[u] = user_regs.regs.gprs[u];
|
|
Packit Service |
97d2fb |
if (! setfunc (0, 16, dwarf_regs, arg))
|
|
Packit Service |
97d2fb |
return false;
|
|
Packit Service |
97d2fb |
/* Avoid conversion double -> integer. */
|
|
Packit Service |
97d2fb |
eu_static_assert (sizeof user_regs.regs.fp_regs.fprs[0]
|
|
Packit Service |
97d2fb |
== sizeof dwarf_regs[0]);
|
|
Packit Service |
97d2fb |
for (unsigned u = 0; u < 16; u++)
|
|
Packit Service |
97d2fb |
{
|
|
Packit Service |
97d2fb |
// Store the double bits as is in the Dwarf_Word without conversion.
|
|
Packit Service |
97d2fb |
union
|
|
Packit Service |
97d2fb |
{
|
|
Packit Service |
97d2fb |
double d;
|
|
Packit Service |
97d2fb |
Dwarf_Word w;
|
|
Packit Service |
97d2fb |
} fpr = { .d = user_regs.regs.fp_regs.fprs[u] };
|
|
Packit Service |
97d2fb |
dwarf_regs[u] = fpr.w;
|
|
Packit Service |
97d2fb |
}
|
|
Packit Service |
97d2fb |
|
|
Packit Service |
97d2fb |
if (! setfunc (16, 16, dwarf_regs, arg))
|
|
Packit Service |
97d2fb |
return false;
|
|
Packit Service |
97d2fb |
dwarf_regs[0] = user_regs.regs.psw.addr;
|
|
Packit Service |
97d2fb |
return setfunc (-1, 1, dwarf_regs, arg);
|
|
Packit Service |
97d2fb |
#endif /* __s390__ */
|
|
Packit Service |
97d2fb |
}
|
|
Packit Service |
97d2fb |
|
|
Packit Service |
97d2fb |
void
|
|
Packit Service |
97d2fb |
s390_normalize_pc (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr *pc)
|
|
Packit Service |
97d2fb |
{
|
|
Packit Service |
97d2fb |
assert (ebl->class == ELFCLASS32);
|
|
Packit Service |
97d2fb |
|
|
Packit Service |
97d2fb |
/* Clear S390 bit 31. */
|
|
Packit Service |
97d2fb |
*pc &= (1U << 31) - 1;
|
|
Packit Service |
97d2fb |
}
|