Exemple #1
0
static void notrace walk_stackframe(struct task_struct *task,
	struct pt_regs *regs, bool (*fn)(unsigned long, void *), void *arg)
{
	unsigned long sp, pc;
	unsigned long *ksp;

	if (regs) {
		sp = GET_USP(regs);
		pc = GET_IP(regs);
	} else if (task == NULL || task == current) {
		const register unsigned long current_sp __asm__ ("sp");
		sp = current_sp;
		pc = (unsigned long)walk_stackframe;
	} else {
		/* task blocked in __switch_to */
		sp = task->thread.sp;
		pc = task->thread.ra;
	}

	if (unlikely(sp & 0x7))
		return;

	ksp = (unsigned long *)sp;
	while (!kstack_end(ksp)) {
		if (__kernel_text_address(pc) && unlikely(fn(pc, arg)))
			break;
		pc = (*ksp++) - 0x4;
	}
}
Exemple #2
0
int main(int argc, char ** argv)
{
    void *cip1, *cip2;
//    GET_IP(cip1);
    GET_IP(back_address);
    jmp_back();
//    GET_IP(cip2);
//    printf("ip: %p, %p, difference: %ld\n", cip2, cip1, cip2 - cip1);
    printf("We are back!\n");
    return 0;
}
Exemple #3
0
static void notrace walk_stackframe(struct task_struct *task,
	struct pt_regs *regs, bool (*fn)(unsigned long, void *), void *arg)
{
	unsigned long fp, sp, pc;

	if (regs) {
		fp = GET_FP(regs);
		sp = GET_USP(regs);
		pc = GET_IP(regs);
	} else if (task == NULL || task == current) {
		const register unsigned long current_sp __asm__ ("sp");
		fp = (unsigned long)__builtin_frame_address(0);
		sp = current_sp;
		pc = (unsigned long)walk_stackframe;
	} else {
		/* task blocked in __switch_to */
		fp = task->thread.s[0];
		sp = task->thread.sp;
		pc = task->thread.ra;
	}

	for (;;) {
		unsigned long low, high;
		struct stackframe *frame;

		if (unlikely(!__kernel_text_address(pc) || fn(pc, arg)))
			break;

		/* Validate frame pointer */
		low = sp + sizeof(struct stackframe);
		high = ALIGN(sp, THREAD_SIZE);
		if (unlikely(fp < low || fp > high || fp & 0x7))
			break;
		/* Unwind stack frame */
		frame = (struct stackframe *)fp - 1;
		sp = fp;
		fp = frame->fp;
		pc = frame->ra - 0x4;
	}
}
static void libbf_save_state(DynAllocDesc* desc, void* ptr)
{
  cast_ptr_to_context(ptr, context);

  long pagesize = libbf_getpagesize();
  
  long regIP = (long)GET_IP(context);
        
  int relative_ip = regIP - (long)desc->current_executable_code;
      
  void* data_ptr = (void*)GET_DATA_PTR_REG(context);
  void* base_data_ptr = desc->executableCodeData.base_data_ptr;
  int relative_data_ptr = (long)data_ptr - (long)base_data_ptr;
      
  /* Restore regular protection for user data pages */
  int ret = libbf_mprotect(desc->current_mem,
                           (COUNT_LOW_ACT_HIGH_PAGES(desc)) * pagesize, PROT_READ | PROT_WRITE);
  if (ret != 0) fatal("mprotect failed\n");
      
  assert (regIP >= (long)desc->current_executable_code &&
          regIP < (long)desc->current_executable_code + desc->size_of_executable_code);

#if defined(__i386__)
{
  int eax = GET_AX(context);
  int ebx = GET_BX(context);
  int ecx = GET_CX(context);
  int edx = GET_DX(context);
  int flags = GET_FL(context);
  int i;
  unsigned char* c = (unsigned char*) desc->current_executable_code;

  FILE* f;
  if (desc->options->suspend_file &&  (f = fopen(desc->options->suspend_file, "wb")) != NULL)
  {
    fwrite(desc->current_executable_code, desc->size_of_executable_code, 1, f);
    fwrite(&relative_ip, sizeof(int), 1, f);
    fwrite(&eax, sizeof(int), 1, f);
    fwrite(&ebx, sizeof(int), 1, f);
    fwrite(&ecx, sizeof(int), 1, f);
    fwrite(&edx, sizeof(int), 1, f);
    fwrite(&flags, sizeof(int), 1, f);
    fwrite(&relative_data_ptr, sizeof(int), 1, f);
    fwrite(&desc->count_active_pages, sizeof(int), 1, f);
    fwrite(base_data_ptr, desc->count_active_pages * pagesize, 1, f);
    fclose(f);
  }
  else
  {
    warning("Can't write in suspend file\n");
  }

  /* seek : 83 c4 0c                add    $12,%esp */
  for(i=desc->size_of_executable_code-3-1;i>=0;i--)
  {
    if (c[i] == 0x83 && c[i+1] == 0xc4 && c[i+2] == 4*3)
    {
      GET_IP(context) = (int)(c + i);
      return;
    }
  }
  SHOULDNT_HAPPEN();
}
#else
{
  long rax = GET_AX(context);
  long rdi = GET_DI(context);
  long rsi = GET_SI(context);
  long rcx = GET_CX(context);
  long rdx = GET_DX(context);
  long flags = GET_FL(context);
  int i;
  unsigned char* c = (unsigned char*) desc->current_executable_code;
  
  FILE* f;
  if (desc->options->suspend_file &&  (f = fopen(desc->options->suspend_file, "wb")) != NULL)
  {
    fwrite(desc->current_executable_code, desc->size_of_executable_code, 1, f);
    fwrite(&relative_ip, sizeof(int), 1, f);
    fwrite(&rax, sizeof(rax), 1, f);
    fwrite(&rdi, sizeof(rdi), 1, f);
    fwrite(&rsi, sizeof(rsi), 1, f);
    fwrite(&rcx, sizeof(rcx), 1, f);
    fwrite(&rdx, sizeof(rdx), 1, f);
    fwrite(&flags, sizeof(flags), 1, f);
    fwrite(&relative_data_ptr, sizeof(int), 1, f);
    fwrite(&desc->count_active_pages, sizeof(int), 1, f);
    fwrite(base_data_ptr, desc->count_active_pages * pagesize, 1, f);
    fclose(f);
  }
  else
  {
    warning("Can't write in suspend file\n");
  }

  /* seek : 48 83 c4 18                add    $24,%rsp */
  for(i=desc->size_of_executable_code-4-1;i>=0;i--)
  {
    if (c[i] == 0x48 && c[i+1] == 0x83 && c[i+2] == 0xc4 && c[i+3] == 8*3)
    {
      GET_IP(context) = (long)(c + i);
      return;
    }
  }
  SHOULDNT_HAPPEN();
}
#endif
}
static
void libbf_compiler_dynalloc_handler(int signum, siginfo_t* info, void* ptr)
{
  if (signum == SIGBUS || (signum == SIGSEGV /* && info->si_code == SEGV_ACCERR */))
  {
    long pagesize = libbf_getpagesize();
    cast_ptr_to_context(ptr, context);
    long fault_page;
    long regIP;
    void* old_mem;
    int old_size;
    long delta_mem;
    int ret;
      
#if defined(__powerpc__)
    DynAllocDesc* desc = (DynAllocDesc*)GET_R14(context);
#elif defined(sun) && defined(__sparc__)
    DynAllocDesc* desc = (DynAllocDesc*)GET_O4(context);
#else
    void** esp = (void**)GET_SP(context);
    DynAllocDesc* desc = (DynAllocDesc*)esp[0];
    assert(esp[1] == (void*)SIGNATURE_1);
    assert(esp[2] == (void*)SIGNATURE_2);
#endif
    if (DEBUG_DYNALLOC) fprintf(stderr, "illegal access to 0x%lX\n", (long)info->si_addr);
    
    assert(desc->signature1 == SIGNATURE_1);
    assert(desc->signature2 == SIGNATURE_2);
    
#if  (defined(__linux__) || defined(__FreeBSD__)  || defined(__OpenBSD__) || defined(WIN32)) && (defined(__i386__) || defined(__x86_64__))
    if (desc->isInterrupted)
    {
      libbf_save_state(desc, ptr);
      return;
    }
#endif

    fault_page = (long)info->si_addr & ~(pagesize-1);

    if (fault_page >= (long)desc->current_mem &&
        fault_page < (long)desc->current_mem + desc->count_low_pages * pagesize)
    {
      if (DEBUG_DYNALLOC) fprintf(stderr, "before current memory\n");
      desc->increase_from_low =
          ((long)desc->current_mem + desc->count_low_pages * pagesize - (long)fault_page) / pagesize;
    }
    else if (fault_page >= (long)desc->current_mem + COUNT_LOW_ACT_PAGES(desc) * pagesize &&
             fault_page < (long)desc->current_mem + COUNT_LOW_ACT_HIGH_PAGES(desc) * pagesize)
    {
      if (DEBUG_DYNALLOC) fprintf(stderr, "after current memory\n");
      desc->increase_from_high =
          1 + (fault_page - ((long)desc->current_mem +
          COUNT_LOW_ACT_PAGES(desc) * pagesize)) / pagesize;
    }
    else
    {
      fatal("dynamic memory allocator strangly failed !");
    }
      
    if (desc->max_total_pages >= 0 && 
        desc->count_active_pages +
        desc->increase_from_low +
        desc->increase_from_high > desc->max_total_pages)
    {
      fatal("Cannot dynamically alloc more than %d pages\n", desc->max_total_pages);
    }

    regIP = (long)GET_IP(context);

    if (DEBUG_DYNALLOC) 
      fprintf(stderr, "0x%lX [0x%lX,0x%lX[\n", regIP, (long)desc->current_executable_code, (long)desc->current_executable_code + desc->size_of_executable_code);
    
    if (!(regIP >= (long)desc->current_executable_code && regIP < (long)desc->current_executable_code + desc->size_of_executable_code))
    {
      fatal("!(regIP >= desc->current_executable_code && regIP < desc->current_executable_code + desc->size_of_executable_code)\n");
    }
    
#if defined(__powerpc__)
    libbf_compiler_desasm(desc->sizeof_elt, (char*)regIP);
#endif
        
    old_mem = desc->current_mem;
    old_size = (COUNT_LOW_ACT_HIGH_PAGES(desc)) * pagesize;
        
    delta_mem = libbf_compiler_dynalloc_realloc(desc);

    GET_DATA_PTR_REG(context) += delta_mem;
    desc->executableCodeData.base_data_ptr = (void*)((long)desc->executableCodeData.base_data_ptr + delta_mem);

    if (DEBUG_DYNALLOC) fprintf(stderr, "dynamic memory allocator can go on\n");
        
    /* Unprotecting all - old - user memory, including upper reserved page, for any latter reuse */
    ret = libbf_mprotect(old_mem,
                         old_size,
                         PROT_READ | PROT_WRITE);
    if (ret != 0) fatal("mprotect failed\n");
    
    /* Discarding now old memory */
    libbf_free_aligned(old_mem);
  
  }
  else
  {
    fatal("unexpected sigsegv at 0x%lX\n", (long)info->si_addr);
  }
}
Exemple #6
0
void WINAPI EXC_RtlUnwind( PEXCEPTION_FRAME pEndFrame, LPVOID unusedEip,
                           PEXCEPTION_RECORD pRecord, DWORD returnEax,
                           CONTEXT *context )
{
    EXCEPTION_RECORD record, newrec;
    PEXCEPTION_FRAME frame, dispatch;

#ifdef __i386__
    context->Eax = returnEax;
#endif

    /* build an exception record, if we do not have one */
    if (!pRecord)
    {
        record.ExceptionCode    = STATUS_UNWIND;
        record.ExceptionFlags   = 0;
        record.ExceptionRecord  = NULL;
        record.ExceptionAddress = GET_IP(context);
        record.NumberParameters = 0;
        pRecord = &record;
    }

    pRecord->ExceptionFlags |= EH_UNWINDING | (pEndFrame ? 0 : EH_EXIT_UNWIND);

    TRACE( "code=%lx flags=%lx\n", pRecord->ExceptionCode, pRecord->ExceptionFlags );

    /* get chain of exception frames */
    frame = NtCurrentTeb()->except;
    while ((frame != (PEXCEPTION_FRAME)0xffffffff) && (frame != pEndFrame))
    {
        /* Check frame address */
        if (pEndFrame && (frame > pEndFrame))
        {
            newrec.ExceptionCode    = STATUS_INVALID_UNWIND_TARGET;
            newrec.ExceptionFlags   = EH_NONCONTINUABLE;
            newrec.ExceptionRecord  = pRecord;
            newrec.NumberParameters = 0;
            RtlRaiseException( &newrec );  /* never returns */
        }
        if (((void*)frame < NtCurrentTeb()->stack_low) ||
            ((void*)(frame+1) > NtCurrentTeb()->stack_top) ||
            (int)frame & 3)
        {
            newrec.ExceptionCode    = STATUS_BAD_STACK;
            newrec.ExceptionFlags   = EH_NONCONTINUABLE;
            newrec.ExceptionRecord  = pRecord;
            newrec.NumberParameters = 0;
            RtlRaiseException( &newrec );  /* never returns */
        }

        /* Call handler */
        switch(EXC_CallHandler( pRecord, frame, context, &dispatch,
                                frame->Handler, EXC_UnwindHandler ))
        {
        case ExceptionContinueSearch:
            break;
        case ExceptionCollidedUnwind:
            frame = dispatch;
            break;
        default:
            newrec.ExceptionCode    = STATUS_INVALID_DISPOSITION;
            newrec.ExceptionFlags   = EH_NONCONTINUABLE;
            newrec.ExceptionRecord  = pRecord;
            newrec.NumberParameters = 0;
            RtlRaiseException( &newrec );  /* never returns */
            break;
        }
        frame = __wine_pop_frame( frame );
    }
}