print_pc: fix multiple personalities support
* syscall.c (print_pc): Choose instruction pointer format depending on current_wordsize, not the size of long integer type. * tests/pc.c: New file. * tests/pc.test: New test. * tests/Makefile.am (check_PROGRAMS): Add pc. (TESTS): Add pc.test. * tests/.gitignore: Add pc.
This commit is contained in:
parent
4f2d1ae243
commit
e96cb621fa
114
syscall.c
114
syscall.c
@ -793,140 +793,138 @@ static long get_regs_error;
|
||||
void
|
||||
print_pc(struct tcb *tcp)
|
||||
{
|
||||
#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
|
||||
sizeof(long) == 8 ? "[????????????????] " : \
|
||||
NULL /* crash */)
|
||||
const char *fmt;
|
||||
const char *bad;
|
||||
|
||||
#if SUPPORTED_PERSONALITIES > 1
|
||||
# define pc_wordsize personality_wordsize[tcp->currpers]
|
||||
#else
|
||||
# define pc_wordsize current_wordsize
|
||||
#endif
|
||||
|
||||
if (pc_wordsize == 4) {
|
||||
fmt = "[%08lx] ";
|
||||
bad = "[????????] ";
|
||||
} else {
|
||||
fmt = "[%016lx] ";
|
||||
bad = "[????????????????] ";
|
||||
}
|
||||
|
||||
#undef pc_wordsize
|
||||
#define PRINTBADPC tprints(bad)
|
||||
|
||||
if (get_regs_error) {
|
||||
PRINTBADPC;
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(I386)
|
||||
tprintf("[%08lx] ", i386_regs.eip);
|
||||
tprintf(fmt, i386_regs.eip);
|
||||
#elif defined(X86_64) || defined(X32)
|
||||
if (x86_io.iov_len == sizeof(i386_regs))
|
||||
tprintf(fmt, (unsigned long) i386_regs.eip);
|
||||
else
|
||||
tprintf(fmt, (unsigned long) x86_64_regs.rip);
|
||||
#elif defined(S390) || defined(S390X)
|
||||
long psw;
|
||||
if (upeek(tcp->pid, PT_PSWADDR, &psw) < 0) {
|
||||
PRINTBADPC;
|
||||
return;
|
||||
}
|
||||
# ifdef S390
|
||||
tprintf("[%08lx] ", psw);
|
||||
# elif S390X
|
||||
tprintf("[%016lx] ", psw);
|
||||
# endif
|
||||
#elif defined(X86_64) || defined(X32)
|
||||
if (x86_io.iov_len == sizeof(i386_regs)) {
|
||||
tprintf("[%08x] ", (unsigned) i386_regs.eip);
|
||||
} else {
|
||||
# if defined(X86_64)
|
||||
tprintf("[%016lx] ", (unsigned long) x86_64_regs.rip);
|
||||
# elif defined(X32)
|
||||
/* Note: this truncates 64-bit rip to 32 bits */
|
||||
tprintf("[%08lx] ", (unsigned long) x86_64_regs.rip);
|
||||
# endif
|
||||
}
|
||||
tprintf(fmt, psw);
|
||||
#elif defined(IA64)
|
||||
long ip;
|
||||
if (upeek(tcp->pid, PT_B0, &ip) < 0) {
|
||||
PRINTBADPC;
|
||||
return;
|
||||
}
|
||||
tprintf("[%08lx] ", ip);
|
||||
tprintf(fmt, ip);
|
||||
#elif defined(POWERPC)
|
||||
long pc = ppc_regs.nip;
|
||||
# ifdef POWERPC64
|
||||
tprintf("[%016lx] ", pc);
|
||||
# else
|
||||
tprintf("[%08lx] ", pc);
|
||||
# endif
|
||||
tprintf(fmt, ppc_regs.nip);
|
||||
#elif defined(M68K)
|
||||
long pc;
|
||||
if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
|
||||
tprints("[????????] ");
|
||||
PRINTBADPC;
|
||||
return;
|
||||
}
|
||||
tprintf("[%08lx] ", pc);
|
||||
tprintf(fmt, pc);
|
||||
#elif defined(ALPHA)
|
||||
long pc;
|
||||
if (upeek(tcp->pid, REG_PC, &pc) < 0) {
|
||||
tprints("[????????????????] ");
|
||||
PRINTBADPC;
|
||||
return;
|
||||
}
|
||||
tprintf("[%08lx] ", pc);
|
||||
tprintf(fmt, pc);
|
||||
#elif defined(SPARC)
|
||||
tprintf("[%08lx] ", sparc_regs.pc);
|
||||
tprintf(fmt, sparc_regs.pc);
|
||||
#elif defined(SPARC64)
|
||||
tprintf("[%08lx] ", sparc_regs.tpc);
|
||||
tprintf(fmt, sparc_regs.tpc);
|
||||
#elif defined(HPPA)
|
||||
long pc;
|
||||
if (upeek(tcp->pid, PT_IAOQ0, &pc) < 0) {
|
||||
tprints("[????????] ");
|
||||
PRINTBADPC;
|
||||
return;
|
||||
}
|
||||
tprintf("[%08lx] ", pc);
|
||||
#elif defined LINUX_MIPSN64
|
||||
tprintf("[%016lx] ", mips_REG_EPC);
|
||||
tprintf(fmt, pc);
|
||||
#elif defined MIPS
|
||||
tprintf("[%08lx] ", (unsigned long) mips_REG_EPC);
|
||||
tprintf(fmt, (unsigned long) mips_REG_EPC);
|
||||
#elif defined(SH)
|
||||
long pc;
|
||||
if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
|
||||
tprints("[????????] ");
|
||||
PRINTBADPC;
|
||||
return;
|
||||
}
|
||||
tprintf("[%08lx] ", pc);
|
||||
tprintf(fmt, pc);
|
||||
#elif defined(SH64)
|
||||
long pc;
|
||||
if (upeek(tcp->pid, REG_PC, &pc) < 0) {
|
||||
tprints("[????????????????] ");
|
||||
PRINTBADPC;
|
||||
return;
|
||||
}
|
||||
tprintf("[%08lx] ", pc);
|
||||
tprintf(fmt, pc);
|
||||
#elif defined(ARM)
|
||||
tprintf("[%08lx] ", arm_regs.ARM_pc);
|
||||
#elif defined(AARCH64)
|
||||
/* tprintf("[%016lx] ", aarch64_regs.regs[???]); */
|
||||
tprintf(fmt, arm_regs.ARM_pc);
|
||||
#elif defined(AVR32)
|
||||
tprintf("[%08lx] ", avr32_regs.pc);
|
||||
tprintf(fmt, avr32_regs.pc);
|
||||
#elif defined(BFIN)
|
||||
long pc;
|
||||
if (upeek(tcp->pid, PT_PC, &pc) < 0) {
|
||||
PRINTBADPC;
|
||||
return;
|
||||
}
|
||||
tprintf("[%08lx] ", pc);
|
||||
tprintf(fmt, pc);
|
||||
#elif defined(CRISV10)
|
||||
long pc;
|
||||
if (upeek(tcp->pid, 4*PT_IRP, &pc) < 0) {
|
||||
PRINTBADPC;
|
||||
return;
|
||||
}
|
||||
tprintf("[%08lx] ", pc);
|
||||
tprintf(fmt, pc);
|
||||
#elif defined(CRISV32)
|
||||
long pc;
|
||||
if (upeek(tcp->pid, 4*PT_ERP, &pc) < 0) {
|
||||
PRINTBADPC;
|
||||
return;
|
||||
}
|
||||
tprintf("[%08lx] ", pc);
|
||||
tprintf(fmt, pc);
|
||||
#elif defined(TILE)
|
||||
# ifdef _LP64
|
||||
tprintf("[%016lx] ", (unsigned long) tile_regs.pc);
|
||||
# else
|
||||
tprintf("[%08lx] ", (unsigned long) tile_regs.pc);
|
||||
# endif
|
||||
tprintf(fmt, (unsigned long) tile_regs.pc);
|
||||
#elif defined(OR1K)
|
||||
tprintf("[%08lx] ", or1k_regs.pc);
|
||||
tprintf(fmt, or1k_regs.pc);
|
||||
#elif defined(METAG)
|
||||
tprintf("[%08lx] ", metag_regs.pc);
|
||||
tprintf(fmt, metag_regs.pc);
|
||||
#elif defined(XTENSA)
|
||||
long pc;
|
||||
if (upeek(tcp->pid, REG_PC, &pc) < 0) {
|
||||
PRINTBADPC;
|
||||
return;
|
||||
}
|
||||
tprintf("[%08lx] ", pc);
|
||||
tprintf(fmt, pc);
|
||||
#elif defined(ARC)
|
||||
tprintf("[%08lx] ", arc_regs.efa);
|
||||
tprintf(fmt, arc_regs.efa);
|
||||
#else
|
||||
# warning print_pc is not implemented for this architecture
|
||||
PRINTBADPC;
|
||||
#endif /* architecture */
|
||||
}
|
||||
|
||||
|
1
tests/.gitignore
vendored
1
tests/.gitignore
vendored
@ -10,6 +10,7 @@ mmsg
|
||||
net-accept-connect
|
||||
netlink_inet_diag
|
||||
netlink_unix_diag
|
||||
pc
|
||||
scm_rights
|
||||
select
|
||||
set_ptracer_any
|
||||
|
@ -15,6 +15,7 @@ check_PROGRAMS = \
|
||||
net-accept-connect \
|
||||
netlink_inet_diag \
|
||||
netlink_unix_diag \
|
||||
pc \
|
||||
scm_rights \
|
||||
select \
|
||||
set_ptracer_any \
|
||||
@ -60,6 +61,7 @@ TESTS = \
|
||||
net.test \
|
||||
net-fd.test \
|
||||
net-yy.test \
|
||||
pc.test \
|
||||
sun_path.test \
|
||||
unix-yy.test \
|
||||
uid.test \
|
||||
|
35
tests/pc.c
Normal file
35
tests/pc.c
Normal file
@ -0,0 +1,35 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
const unsigned long size = sysconf(_SC_PAGESIZE);
|
||||
const unsigned long mask = ~(size - 1);
|
||||
|
||||
/* write instruction pointer length to the log */
|
||||
if (write(-1, NULL, 2 * sizeof(void *)) >= 0)
|
||||
return 77;
|
||||
/* just a noticeable line in the log */
|
||||
if (munmap(&munmap, 0) >= 0)
|
||||
return 77;
|
||||
|
||||
int pid = fork();
|
||||
if (pid < 0)
|
||||
return 77;
|
||||
|
||||
if (!pid) {
|
||||
munmap((void *) ((unsigned long) &munmap & mask), size);
|
||||
/* SIGSEGV is expected */
|
||||
munmap((void *) (((unsigned long) &munmap & mask) + size), size);
|
||||
return 77;
|
||||
}
|
||||
|
||||
int status;
|
||||
if (wait(&status) != pid ||
|
||||
!WIFSIGNALED(status) ||
|
||||
WTERMSIG(status) != SIGSEGV)
|
||||
return 77;
|
||||
|
||||
return 0;
|
||||
}
|
47
tests/pc.test
Executable file
47
tests/pc.test
Executable file
@ -0,0 +1,47 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Check -i option.
|
||||
|
||||
. "${srcdir=.}/init.sh"
|
||||
|
||||
check_prog grep
|
||||
|
||||
OUT="$LOG.out"
|
||||
|
||||
./pc > /dev/null ||
|
||||
framework_skip_ 'munmap/fork/wait do not behave as expected'
|
||||
|
||||
args="-if ./pc"
|
||||
$STRACE $args > "$OUT" 2> "$LOG" || {
|
||||
cat "$LOG"
|
||||
fail_ "$STRACE $args does not work"
|
||||
}
|
||||
|
||||
len="$(sed -n 's/^\[[[:xdigit:]]\+\] write(-1, NULL, \([[:digit:]]\{1,2\}\))[[:space:]]\+= -1 .*/\1/p' "$LOG")" &&
|
||||
[ -n "$len" ] &&
|
||||
pid="$(sed -n 's/^\[[[:xdigit:]]\{'"$len"'\}\] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=\([[:digit:]]\+\), .*/\1/p' "$LOG")" &&
|
||||
[ -n "$pid" ] &&
|
||||
ip="$(sed -n 's/^\[pid \+'"$pid"'\] \[\([[:xdigit:]]\{'"$len"'\}\)] --- SIGSEGV {.*} ---$/\1/p' "$LOG")" &&
|
||||
[ -n "$ip" ] &&
|
||||
addr="$(echo "$ip" |sed 's/^0\+//')" &&
|
||||
[ -n "$addr" ] || {
|
||||
cat "$LOG"
|
||||
fail_ "$STRACE $args output mismatch"
|
||||
}
|
||||
|
||||
grep_log()
|
||||
{
|
||||
LC_ALL=C grep -x -e "$*" < "$LOG" > /dev/null || {
|
||||
cat "$LOG"
|
||||
fail_ "$STRACE $args output mismatch"
|
||||
}
|
||||
}
|
||||
|
||||
grep_log '\[[[:xdigit:]]\{'"$len"'\}\] munmap(0x[[:xdigit:]]\+, 0)[[:space:]]\+= -1 .*'
|
||||
grep_log '\[pid \+'"$pid"'\] \['"$ip"'\] --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x'"$addr"'} ---'
|
||||
grep_log '\[pid \+'"$pid"'\] \[?\{'"$len"'\}\] +++ killed by SIGSEGV +++'
|
||||
grep_log '\[?\{'"$len"'\}\] +++ exited with 0 +++'
|
||||
|
||||
rm -f "$OUT"
|
||||
|
||||
exit 0
|
Loading…
x
Reference in New Issue
Block a user