ia32调用约定寄存器被破坏?

时间:2014-09-15 18:47:37

标签: c x86 stack cpu-registers

我有以下两个文件,第一个为SIGUSR1创建一个信号处理程序,它在中断的上下文中设置对函数foo()的伪调用。第二个文件是用于访问IA32寄存器的模板头。

stack.c:

#ifdef HARMONY
#define LINUX
#include "hythread.h"
#endif

#ifndef _GNU_SOURCE
#define _GNU_SOURCE             // so that string.h will include strsignal()
#endif
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
#include <stdarg.h>             // va_list, va_start(), va_end()
#ifndef __USE_GNU         // Deal with current ucontext ugliness.  The current
#define __USE_GNU         // mess of asm/ucontext.h & sys/ucontext.h and their
#include <sys/ucontext.h> // mutual exclusion on more recent versions of gcc
#undef __USE_GNU          // dictates this ugly hack.
#else
#include <sys/ucontext.h>
#endif
#include <assert.h>

#include "linux_ucontext.h"

#define DBG(fncn,name) if (fncn) { perror(name); return 1; }

void foo(void *fp) {
  printf("Inside foo(%p)\n", fp);
}

typedef long unsigned int* Address;

void handler(int signo, siginfo_t *si, void *context) {
  if (signo == SIGUSR1) {
    printf("Handling SIGUSR1...\n");

    // Set fake pointer (0xDEADBEEF) as first argument to foo()
    Address sp = (Address)IA32_ESP(context);
    IA32_ESP(context) = IA32_ESP(context) - sizeof(void *);
    sp = (Address)IA32_ESP(context);
    ((Address *)sp)[0]  = IA32_EIP(context);
    IA32_EAX(context) = 0xDEADBEEF;

    // Put return address of interrupted instruction onto stack
    IA32_ESP(context) = IA32_ESP(context) - sizeof(void *);
    sp = IA32_ESP(context);
    ((Address *)sp)[0] = IA32_EIP(context);

    // Setup function call to foo()
    IA32_EIP(context) = foo;

    return;
  }
  printf("Received unknown signal signo=%d\n",signo);
}

int main(int argc, char *argv[]) {

  struct sigaction action;
  memset(&action, 0, sizeof(action));
  action.sa_sigaction = &handler;

  // Mask all signals from reaching handler while handler is running
  DBG(sigfillset(&(action.sa_mask)),"sigfillset");

  DBG(sigdelset(&(action.sa_mask), SIGCONT),"sigdelset");
  action.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART;

  action.sa_sigaction = &handler;
  DBG(sigaction(SIGUSR1, &action, 0),"sigaction")

  int count = 0;
  while (1) {
    sleep(1);
    printf("Inside while loop %08d...\n",count);
    count += 1;
  }

}

linux_context.h:

/*
 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
 *
 *  This file is licensed to You under the Eclipse Public License (EPL);
 *  You may not use this file except in compliance with the License. You
 *  may obtain a copy of the License at
 *
 *      http://www.opensource.org/licenses/eclipse-1.0.php
 *
 *  See the COPYRIGHT.txt file distributed with this work for information
 *  regarding copyright ownership.
 */
#ifndef JRVM_LINUX_IA32_UCONTEXT
#define JRVM_LINUX_IA32_UCONTEXT

#define __MC(context) ((ucontext_t*)context)->uc_mcontext
#define __GREGS(context) (__MC(context).gregs)

#ifndef __x86_64__
#  define IA32_EAX(context) (__GREGS(context)[REG_EAX])
#  define IA32_EBX(context) (__GREGS(context)[REG_EBX])
#  define IA32_ECX(context) (__GREGS(context)[REG_ECX])
#  define IA32_EDX(context) (__GREGS(context)[REG_EDX])
#  define IA32_EDI(context)  (__GREGS(context)[REG_EDI])
#  define IA32_ESI(context)  (__GREGS(context)[REG_ESI])
#  define IA32_EBP(context)  (__GREGS(context)[REG_EBP])
#  define IA32_ESP(context) (__GREGS(context)[REG_ESP])
#  define IA32_EIP(context)  (__GREGS(context)[REG_EIP])

#  define IA32_CS(context)  (__GREGS(context)[REG_CS])
#  define IA32_DS(context)  (__GREGS(context)[REG_DS])
#  define IA32_ES(context)  (__GREGS(context)[REG_ES])
#  define IA32_FS(context)  (__GREGS(context)[REG_FS])
#  define IA32_GS(context)  (__GREGS(context)[REG_GS])
#  define IA32_SS(context)  (__GREGS(context)[REG_SS])

#  define IA32_OLDMASK(context) (__MC(context).oldmask)
#  define IA32_FPFAULTDATA(context)     (__MC(context).cr2)
#else
#  define IA32_EAX(context) (__GREGS(context)[REG_RAX])
#  define IA32_EBX(context) (__GREGS(context)[REG_RBX])
#  define IA32_ECX(context) (__GREGS(context)[REG_RCX])
#  define IA32_EDX(context) (__GREGS(context)[REG_RDX])
#  define IA32_EDI(context)  (__GREGS(context)[REG_RDI])
#  define IA32_ESI(context)  (__GREGS(context)[REG_RSI])
#  define IA32_EBP(context)  (__GREGS(context)[REG_RBP])
#  define IA32_ESP(context) (__GREGS(context)[REG_RSP])
#  define IA32_EIP(context)  (__GREGS(context)[REG_RIP])
#endif

#define IA32_EFLAGS(context)  (__GREGS(context)[REG_EFL])
#define IA32_TRAPNO(context) (__GREGS(context)[REG_TRAPNO])
#define IA32_ERR(context) (__GREGS(context)[REG_ERR])
#define IA32_FALUTVADDR(context) (__GREGS(context)[REG_CS])

#define IA32_FPREGS(context) (__MC(context).fpregs)

// reg = 0..7, n = 0 .. 3
#define IA32_STMM(context, reg, n) (IA32_FPREGS(context)->_st[reg].significand[n])
#define IA32_STMMEXP(context, reg) (IA32_FPREGS(context)->_st[reg].exponent)

/* Currently unused
#define IA32_XMM(context, reg, n) \
*/

#endif

当我编译并运行它,并使用SIGUSR1命中进程时,foo()被正确调用并返回到while循环。但是,当我设置一个类似的信号处理程序来中断某些任意代码(运行JVM)时,假的&#34; foo()&#34;正确执行,但当它返回到任意中断代码时,进程分段出错。

我是否在假函数调用中破坏了一些寄存器?在尝试将0xDEADBEEF传递给foo时我做错了什么(现在它似乎正在打印垃圾指针)?

0 个答案:

没有答案