int do_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { struct emulated_sigaction *k; struct sigaction act1; int host_sig; if (sig < 1 || sig > NSIG) return -EINVAL; k = &sigact_table[sig - 1]; #if defined(DEBUG_SIGNAL) fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n", sig, (int)act, (int)oact); #endif if (oact) { #if defined(DEBUG_SIGNAL) fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n", sig, (int)act, (int)oact); #endif oact->sa_handler = tswapl(k->sa.sa_handler); oact->sa_flags = tswapl(k->sa.sa_flags); oact->sa_mask = tswapl(k->sa.sa_mask); } if (act) { #if defined(DEBUG_SIGNAL) fprintf(stderr, "sigaction handler 0x%x flag 0x%x mask 0x%x\n", act->sa_handler, act->sa_flags, act->sa_mask); #endif k->sa.sa_handler = tswapl(act->sa_handler); k->sa.sa_flags = tswapl(act->sa_flags); k->sa.sa_mask = tswapl(act->sa_mask); /* we update the host signal state */ host_sig = target_to_host_signal(sig); if (host_sig != SIGSEGV && host_sig != SIGBUS) { #if defined(DEBUG_SIGNAL) fprintf(stderr, "sigaction handler going to call sigaction\n"); #endif sigfillset(&act1.sa_mask); act1.sa_flags = SA_SIGINFO; if (k->sa.sa_flags & SA_RESTART) act1.sa_flags |= SA_RESTART; /* NOTE: it is important to update the host kernel signal ignore state to avoid getting unexpected interrupted syscalls */ if (k->sa.sa_handler == SIG_IGN) { act1.sa_sigaction = (void *)SIG_IGN; } else if (k->sa.sa_handler == SIG_DFL) { act1.sa_sigaction = (void *)SIG_DFL; } else { act1.sa_sigaction = host_signal_handler; } sigaction(host_sig, &act1, NULL); } } return 0; }
/* abort execution with signal */ void QEMU_NORETURN force_sig(int sig) { int host_sig; host_sig = target_to_host_signal(sig); fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n", sig, strsignal(host_sig)); _exit(-host_sig); }
/* abort execution with signal */ void __attribute((noreturn)) force_sig(int sig) { int host_sig; host_sig = target_to_host_signal(sig); fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n", sig, strsignal(host_sig)); _exit(-host_sig); }
uint32_t do_syscall_arm(ProgramBase *prog, uint32_t num, uint32_t arg1,uint32_t arg2, uint32_t arg3,uint32_t arg4,uint32_t arg5, uint32_t arg6, FILE *syscallTrace) { #ifdef DEBUG2 printf ("syscall %d \n", num); #endif uint32_t ret; void *p; #if defined (CONFIG_ESESC_system) || defined (CONFIG_ESESC_user) struct timespec startTime; clock_gettime(CLOCK_REALTIME,&startTime); #endif char tmp_str[128]; char pc[32]; char systrace_syscall_num[32]; char emul_syscall_num[32]; int i, j, ret1; regex_t re1; regmatch_t match[3]; if (syscallTrace != NULL) { // Example trace file section // //---------- //pc: 0x8174 //syscall: 122 //Linux //masca1 //3.0.0-1205-omap4 //#10-Ubuntu SMP PREEMPT Thu Sep 29 03:57:24 UTC 2011 //armv7l //---------- //pc: 0x8230 //syscall: 4 //---------- //printf("Advance to the section \n"); fgets(tmp_str, sizeof tmp_str, syscallTrace); tmp_str[strlen (tmp_str) - 1] = '\0'; memset(tmp_str, '\0', 128); // read pc fgets(pc, sizeof pc, syscallTrace); pc[strlen (pc) - 1] = '\0'; // read syscall number fgets(tmp_str, sizeof tmp_str, syscallTrace); tmp_str[strlen (tmp_str) - 1] = '\0'; //printf("pc %s, syscall %s \n", pc, tmp_str); ret1 = regcomp(&re1, "syscall: ([0-9]+)", REG_EXTENDED); ret1 = regexec(&re1, tmp_str, 2, match, 0); if(!ret1) { j = 0; for(i = match[1].rm_so; i < match[1].rm_eo; i++) { systrace_syscall_num[j] = tmp_str[i]; j++; } systrace_syscall_num[j] = '\0'; }else{ I(0); } sprintf(emul_syscall_num, "%d", num); // Sanity check for syscall number if (strcmp(systrace_syscall_num, emul_syscall_num) != 0) { printf("Emulator syscall trace and expected syscall trace are out of sync \n"); printf(" syscall num - Expected: %s, Emulator: %s\n", systrace_syscall_num, emul_syscall_num); I(0); // exit(0); } } switch(num) { case TARGET_NR_exit: exit(arg1); return 0; break; case TARGET_NR_exit_group: exit(arg1); return 0; break; case TARGET_NR_write: ret = write(arg1, prog->g2h(arg2), arg3); return ret; break; case TARGET_NR_read: if (arg3 == 0) { ret = 0; }else{ ret = read(arg1, prog->g2h(arg2), arg3); } return ret; break; /* case TARGET_NR_ioctl: do_ioctl(prog, arg1, arg2, arg3); return 0; break;*/ case TARGET_NR_lseek: ret = lseek(arg1, arg2, arg3); return ret; break; case TARGET_NR_gettimeofday: { // FIXME: Not correct struct timeval tv; gettimeofday(&tv, NULL); } return 0; break; case TARGET_NR_open: // FIXME: how to check if this is a open(a,b,c) or open(a,b) ret = open((const char *)prog->g2h(arg1), arg2); return ret; break; case TARGET_NR_close: ret = close(arg1); return ret; break; case TARGET_NR_mkdir: p = lock_user_string(prog, arg1); ret = mkdir((const char *)p, arg2); return ret; break; case TARGET_NR_rmdir: p = lock_user_string(prog, arg1); ret = rmdir((const char *)p); return ret; break; case TARGET_NR_rename: { void *p2; p = lock_user_string(prog, arg1); p2 = lock_user_string(prog, arg2); if (!p || !p2) ret = -TARGET_EFAULT; else rename((const char *)p, (const char *)p2); } return 0; break; case TARGET_NR_uname: // copy 390 bytes from syscalltrace to buf //Linux //masca1 //3.0.0-1205-omap4 //#10-Ubuntu SMP PREEMPT Thu Sep 29 03:57:24 UTC 2011 { struct utsname *uts_buf = (struct utsname *)prog->g2h(arg1); if (syscallTrace != NULL) { for (i = 0; i < 5; i++) { memset(tmp_str, '\0', 65); fgets(tmp_str, sizeof tmp_str, syscallTrace); tmp_str[strlen (tmp_str) - 1] = '\0'; if(i == 0) strcpy(uts_buf->sysname, tmp_str); else if(i == 1) strcpy(uts_buf->nodename, tmp_str); else if(i == 2) strcpy(uts_buf->release, tmp_str); else if(i == 3) strcpy(uts_buf->version, tmp_str); else if(i == 4) strcpy(uts_buf->machine, tmp_str); } } else { if (uname(uts_buf) < 0) return (-1); } } return 0; break; case TARGET_NR_brk: { if (!arg1) { return target_brk; } else if(arg1 < target_original_brk) { return target_brk; } else { if(arg1 < brk_page) { if(arg1 > target_brk) { // initialize as it may contain garbage due to a previous heap usage // (grown then shrunken) memset(prog->g2h(target_brk), 0, arg1 - target_brk); } // deallocate is handled automatically here. target_brk = arg1; return target_brk; } // Need to allocate memory. // We can't call local host brk() system call which tends to change the // simulator program's brk_addr. // What we need to adjust here is the simulated virtual memory data segment. // so simulate brk here by calling realloc to reallocate simulator data segment. uint32_t size_incr = PAGE_ALIGN_UP(arg1 - brk_page); uint32_t old_size; uint32_t *data_ptr = NULL; data_ptr = prog->get_data_buffer(&old_size); uint8_t *new_data_ptr = (uint8_t *)realloc(data_ptr, (old_size + size_incr)); if (new_data_ptr != NULL) { prog->set_data_buffer((old_size + size_incr), new_data_ptr); target_brk = arg1; brk_page = PAGE_ALIGN_UP(target_brk); return target_brk; } else { return (-1); } } } return target_brk;; break; case TARGET_NR_fstat64: { if (syscallTrace == NULL) { ret = fstat(arg1, (struct stat *)prog->g2h(arg2)); return ret; } else { // copy 144 bytes (size of stat structure) from systrace file // number of lines in the file: total 144 bytes/8 bytes per line = 18 lines for (i=0; i < 18; i++) { memset(tmp_str, '\0', 128); fgets(tmp_str, 128, syscallTrace); long long int val = strtoull(tmp_str, NULL, 16); memcpy( (prog->g2h(arg2 + (i * 8) )), &val, 8); } } } return 0; break; case TARGET_NR_mmap2: { if (arg1 != 0x00000000) { // FIXME: This is the non-zero address case. // The address gives a hint to the kernel about where to map the file. // We might still do a malloc but need to remember a mapping of the native // address (i.e arg1) to pointer returned by malloc. printf("TARGET_NR_mmap2 map address not zero!!! This case is not handled \n"); exit(-1); } uint8_t *p = (uint8_t *)malloc(arg2); if (p == MAP_FAILED) return -1; else { prog->set_mem_mapped_file_endpts((long)p, arg2); return (long)p; } } return 0; printf("return address 0x%08x \n", p); break; case TARGET_NR_getpid: getpid(); return 0; break; case TARGET_NR_kill: kill(arg1, target_to_host_signal(arg2)); return 0; break; case TARGET_NR_pause: pause(); return 0; break; #ifdef TARGET_NR_shutdown case TARGET_NR_shutdown: shutdown(arg1, arg2); return 0; break; #endif #ifdef TARGET_NR_semget case TARGET_NR_semget: semget(arg1, arg2, arg3); return 0; break; #endif case TARGET_NR_setdomainname: p = lock_user_string(prog, arg1); setdomainname((const char *)p, arg2); return 0; break; case TARGET_NR_getsid: getsid(arg1); return 0; break; #if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */ case TARGET_NR_fdatasync: fdatasync(arg1); return 0; break; #endif #ifdef TARGET_NR_getuid32 case TARGET_NR_getuid32: getuid(); return 0; break; #endif case TARGET_NR_ioctl: printf("ioctl syscall not implemented\n"); return 0; break; default: printf("syscall %d is not implemented\n", num); exit(-1); } }