syscall.c | 21 +++++++++++++++++++-- 1 files changed, 19 insertions(+), 2 deletions(-) diff --git a/syscall.c b/syscall.c index e66ac0a95582..edd9cb804318 100644 --- a/syscall.c +++ b/syscall.c @@ -901,14 +901,31 @@ get_scno(struct tcb *tcp) long val; int pid = tcp->pid; + /* Check the high bits of eflags for processor mode */ + if (upeek(tcp, 8*EFLAGS, &val) < 0) + return -1; + val >>= 32; /* Check CS register value. On x86-64 linux it is: * 0x33 for long mode (64 bit) * 0x23 for compatibility mode (32 bit) * It takes only one ptrace and thus doesn't need * to be cached. */ - if (upeek(tcp, 8*CS, &val) < 0) - return -1; + switch (val & 3) { + case 0: + /* Legacu case: check CS */ + if (upeek(tcp, 8*CS, &val) < 0) + return -1; + break; + case 1: + /* "Long mode" value */ + val = 0x33; + break; + case 2: + /* Compatibility mode */ + val = 0x23; + break; + } switch (val) { case 0x23: currpers = 1; break; case 0x33: currpers = 0; break;