⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 emit.c

📁 二进制翻译的一个软件
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (c) 2005, Johns Hopkins University and The EROS Group, LLC. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * *  * Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. *  * Redistributions in binary form must reproduce the above *    copyright notice, this list of conditions and the following *    disclaimer in the documentation and/or other materials provided *    with the distribution. * *  * Neither the name of the Johns Hopkins University, nor the name *    of The EROS Group, LLC, nor the names of their contributors may *    be used to endorse or promote products derived from this *    software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */#include <stdbool.h>#include <assert.h>#include <stdio.h>#include "switches.h"#include "debug.h"#include "util.h"#include "machine.h"#include "decode.h"#include "emit.h"#include "emit-support.h"#include "xlcore.h"#include "perf.h"#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/user.h>#include <fcntl.h>#include <errno.h>#include <string.h>#include <math.h>#include <stdlib.h>#include <sched.h>#include <asm/unistd.h>#ifdef INLINE_EMITTERS#define INLINE static inline#include "emit-inline.c"#else#define INLINE#endif#include "xlate-helper.c"/*********************************************************************Emit Normal - All other instructions*********************************************************************/boolemit_normal(machine_t *M, decode_t *d){  unsigned i;  unsigned count = M->next_eip - d->decode_eip;  DEBUG(emits)    fprintf(DBG, "%lu: Normal %lx %s\n", M->nTrInstr, d->decode_eip, ((OpCode *) d->pEntry)->disasm);#ifdef PROFILE  M->ptState->s_normal_cnt++;  bb_emit_inc(M, MFLD(M, ptState->normal_cnt));#endif  /*   for (i = 0; i < count; i++) { */  /* #ifdef STATIC_PASS */  /*     bb_emit_byte(M, ((unsigned char *)d->mem_decode_eip)[i]);  */  /* #else */  /*     bb_emit_byte(M, ((unsigned char *)d->decode_eip)[i]);  */  /* #endif */  /*   } */#ifdef STATIC_PASS  memcpy(M->bbOut, (unsigned char *)d->mem_decode_eip, count);#else  memcpy(M->bbOut, (unsigned char *)d->decode_eip, count);#endif  M->bbOut += count;  return false; }/*********************************************************************Emit INT - To capture exit only*********************************************************************/#define Aux1(x) (x), PERC((x), M->ptState->total_cnt)#define Aux2(x) (x), PERC((x), M->ptState->s_total_cnt)#if (defined(USE_STATIC_DUMP) || defined(STATIC_PASS))#define ENABLE_DUMP_FUNCTION#endif#ifdef ENABLE_DUMP_FUNCTION/* 1) Warning: Will modify str */voiddump_to_file(machine_t *M, char *str){  char arg[300];   unsigned long i;  struct stat buf;  unsigned long len = strlen(str);  /* This has to be mmaped eventually ...     Better abort than buffer overflow */  if(len > 300) {    fprintf(DBG, "len > 300; Temporarily aborting; Did not dump.");    return;  }  for(i=0; i<len; i++)    if(str[i] == '/')      str[i] = '_';      #ifdef CHECK_DUMP_DIR  if(stat("/tmp/vdebug-dump", &buf) == -1 && errno == ENOENT)    system("mkdir /tmp/vdebug-dump");#endif  int fd;  extrabytes = (sizeof(machine_t) + sizeof(pt_state)) % PAGE_SIZE;    sprintf(arg, "/tmp/vdebug-dump/%s-dump", str);  fd = open(arg, O_CREAT | O_RDWR | O_TRUNC, S_IRWXU);  i = write(fd, M, sizeof(machine_t));   i = write(fd, M->ptState, sizeof(pt_state));   i = write(fd, M, extrabytes);  // waste  close(fd);    sprintf(arg, "/tmp/vdebug-dump/%s-addr", str);  fd = open(arg, O_CREAT | O_RDWR | O_TRUNC, S_IRWXU);  i = write(fd, &M, sizeof(machine_t *));   close(fd);  }#endifvoid exit_stub(machine_t *M){  unsigned long i;  /* This might cause some problems at least collisions due to     the fixed size of buffers. However, I believe I      removed all cases of buffer overflow */  char str[300];  char arg[300];  sprintf(arg, "/proc/%d/exe", getpid());  i = readlink(arg,str,sizeof(str));  str[i] = '\0';  FILE *f;#ifdef PROFILE_TRANSLATION  f = fopen("timer", "a");  unsigned long long start_time = M->ptState->tot_time;  unsigned long long end_time = read_timer();   M->ptState->tot_time = end_time - start_time;  fprintf(f, "Process: %s\n", str);  fprintf(f, "Start Time        = %llu\n", start_time);  fprintf(f, "End Time          = %llu\n", end_time);    fprintf(f, "Translation Time  = %llu\n", M->ptState->trans_time);  fprintf(f, "Total Time        = %llu\n", M->ptState->tot_time);  fprintf(f, "Translation Time% = %0.3f\n", 	  PERC(M->ptState->trans_time, M->ptState->tot_time));  fprintf(f, "Total bytes       = %lu\n", (M->bbOut - M->bbCache));    fprintf(f, "Cycles per byte   = %0.3f\n\n\n", 	  (float)M->ptState->trans_time / (M->bbOut - M->bbCache));    fclose(f);  return;#endif#ifdef PROFILE_BB_CNT  f = stdout;     fprintf(f, "Process         : %s\n", str);  fprintf(f, "Total count     = %lu\n", M->ptState->bb_cnt);  return;#endif    #if defined(PROFILE) || defined(PROFILE_RET_MISS)  FILE *F = fopen("stats", "a");#endif#ifdef PROFILE   M->ptState->total_cnt =     (unsigned long long) M->ptState->normal_cnt +     (unsigned long long) M->ptState->jmp_cond_cnt +     (unsigned long long) M->ptState->jmp_dir_cnt +    (unsigned long long) M->ptState->jmp_indr_cnt +    (unsigned long long) M->ptState->call_dir_cnt +    (unsigned long long) M->ptState->call_indr_cnt +    (unsigned long long) M->ptState->ret_cnt +    (unsigned long long) M->ptState->ret_Iw_cnt ;   M->ptState->s_total_cnt =     (unsigned long long) M->ptState->s_normal_cnt +     (unsigned long long) M->ptState->s_jmp_cond_cnt +     (unsigned long long) M->ptState->s_jmp_dir_cnt +    (unsigned long long) M->ptState->s_jmp_indr_cnt +    (unsigned long long) M->ptState->s_call_dir_cnt +    (unsigned long long) M->ptState->s_call_indr_cnt +    (unsigned long long) M->ptState->s_ret_cnt +    (unsigned long long) M->ptState->s_ret_Iw_cnt ;   fprintf(F, "Process 			: %s\n", str);      fprintf(F, "         Static Statistics\n");  fprintf(F, "Total No. of Instructions 	= %llu  100%\n", 	  M->ptState->s_total_cnt);  fprintf(F, "Normal Instructions 		= %lu  %0.3f%\n", 	  Aux2(M->ptState->s_normal_cnt));  fprintf(F, "Conditional Jump 		= %lu  %0.3f%\n", 	  Aux2(M->ptState->s_jmp_cond_cnt));   fprintf(F, "Direct Jump 			= %lu  %0.3f%\n", 	  Aux2(M->ptState->s_jmp_dir_cnt));   fprintf(F, "Indirect Jump 			= %lu  %0.3f%\n", 	  Aux2(M->ptState->s_jmp_indr_cnt));   fprintf(F, "Direct Call			= %lu  %0.3f%\n", 	  Aux2(M->ptState->s_call_dir_cnt));   fprintf(F, "Indirect Call 			= %lu  %0.3f%\n", 	  Aux2(M->ptState->s_call_indr_cnt));   fprintf(F, "Return 				= %lu  %0.3f%\n", 	  Aux2(M->ptState->s_ret_cnt));   fprintf(F, "Return IW 			= %lu  %0.3f%\n", 	  Aux2(M->ptState->s_ret_Iw_cnt));   fprintf(F, "         Dynamic Statistics\n");  fprintf(F, "Total No. of Instructions 	= %lu  100%\n", 	  M->ptState->total_cnt);  fprintf(F, "Normal Instructions 		= %lu  %0.3f%\n", 	  Aux1(M->ptState->normal_cnt));  fprintf(F, "Conditional Jump 		= %lu  %0.3f%\n", 	  Aux1(M->ptState->jmp_cond_cnt));   fprintf(F, "Direct Jump 			= %lu  %0.3f%\n", 	  Aux1(M->ptState->jmp_dir_cnt));   fprintf(F, "Indirect Jump 			= %lu  %0.3f%\n", 	  Aux1(M->ptState->jmp_indr_cnt));   fprintf(F, "Direct Call 			= %lu  %0.3f%\n", 	  Aux1(M->ptState->call_dir_cnt));   fprintf(F, "Indirect Call 			= %lu  %0.3f%\n", 	  Aux1(M->ptState->call_indr_cnt));   fprintf(F, "Return 				= %lu  %0.3f%\n", 	  Aux1(M->ptState->ret_cnt));   fprintf(F, "Return IW 			= %lu  %0.3f%\n", 	  Aux1(M->ptState->ret_Iw_cnt)); #endif#ifdef PROFILE  fprintf(F, "         Basic-Block Statistics\n");#endif#ifdef PROFILE_RET_MISS    unsigned long p=0, q=0;  for(p=0; p<CALL_TABLE_SIZE; p++)    if(M->call_hash_table[p] != (unsigned long)M->ret_calls_fast_dispatch_bb)      q++;#ifdef PROFILE  fprintf(F, "Returns going to wrong call site = %lu [%.3f%%]\n", 	  M->ptState->ret_miss_cnt, 	  PERC(M->ptState->ret_miss_cnt, 	       M->ptState->ret_cnt + M->ptState->ret_Iw_cnt));  fprintf(F, "Returns going to fast-dispatch   = %lu [%.3f%%]\n", 	  M->ptState->ret_ret_miss_cnt, 	  PERC(M->ptState->ret_ret_miss_cnt, 	       M->ptState->ret_cnt + M->ptState->ret_Iw_cnt));  M->ptState->ret_miss_cnt += M->ptState->ret_ret_miss_cnt;  fprintf(F, "Returns missed Optimization = %lu [%.3f%%]\n", 	  M->ptState->ret_miss_cnt, 	  PERC(M->ptState->ret_miss_cnt, 	       M->ptState->ret_cnt + M->ptState->ret_Iw_cnt));  #else  fprintf(F, "Returns going to wrong call site = %lu\n", M->ret_miss_cnt);  fprintf(F, "Returns going to fast-dispatch   = %lu\n", M->ret_ret_miss_cnt);  M->ret_miss_cnt += M->ret_ret_miss_cnt;  fprintf(F, "Returns missed Optimization = %lu\n", M->ret_miss_cnt);  #endif  fprintf(F, "%lu / %lu = %0.3f%% buckets changed\n", q, p, ((float)q*100)/((float)p));  fprintf(F, "BBs with COLD pe = %lu / %lu [%0.3f%%]\n", 	  M->ptState->cold_cnt, 	  M->no_of_bbs, 	  PERC(M->ptState->cold_cnt, M->no_of_bbs));      fflush(F);#endif  #ifdef PROFILE  fprintf(F, "Total No. of BBs 		= %lu\n", M->no_of_bbs);  fprintf(F, "No. of BBs with cmp-jmp headers = %lu %0.3f%\n", 	  M->ptState->hash_nodes_cnt, 	  PERC(M->ptState->hash_nodes_cnt, M->no_of_bbs));  fprintf(F, "BBCache: Total size 		= %lu\n", BBCACHE_SIZE);  fprintf(F, "BBCache: No. of Bytes used 	= %lu %0.3f%\n", (M->bbOut-M->bbCache), 	  PERC((M->bbOut-M->bbCache), BBCACHE_SIZE));  /*   bucket_entry *b = (bucket_entry *)M->hash_table;  */  /*   unsigned long ch_used_cnt = 0; */  /*   unsigned long max_len = 0; */  /*   unsigned long len = 0; */  /*   bb_header *h; */  /*   for(i=0; i<NBUCKETS; i++, b++) */  /*     if((unsigned long)(b->rel + &(b->filler[0])) != (unsigned long)(M->slow_dispatch_bb)) */  /*       { */  /* 	ch_used_cnt++; */  /* 	len = 0; */  /* 	h = (bb_header *)(b->rel + &(b->filler[0])); */  /* 	while((unsigned long)h != (unsigned long)(M->slow_dispatch_bb)) */  /* 	  { */  /* 	    len++; */  /* 	    h = (bb_header *) ((unsigned long)(h->next_bb) + (unsigned long) (&(h->pop_ebx))); */  /* 	  } */  /* 	if(len > max_len) */  /* 	  max_len = len; */  /*       } */		  /*   fprintf(F, "Total (Code) Hash_Table buckets	= %lu\n", NBUCKETS);  */  /*   fprintf(F, "Hash Buckets used		= %lu %0.3f%\n", ch_used_cnt, PERC(ch_used_cnt, NBUCKETS));  */  /*   fprintf(F, "Maximim length of any chain	= %lu\n", max_len); */  /*   fprintf(F, "\n\n\n");  */#endif  #if defined(PROFILE) || defined(PROFILE_RET_MISS)  fclose(F);#endif#ifdef USE_STATIC_DUMP   if(M->dump == true) {    dump_to_file(M, str);  }#endif#ifdef OUTPUT_BB_STAT  {    FILE *F = fopen("bbstat", "w");    for(i=0; i<M->no_of_bbs; i++) {      fprintf(F, "%lx\n", M->bb_entry_nodes[i].src_bb_eip);    }  }#endif#ifdef PROFILE_BB_STATS  {    unsigned long nrelocbbs=0, ntrelocbbs=0, nactualbbs=0;    unsigned long nrelocbytes=0, ntrelocbytes=0, nactualbytes = M->bbOut - M->bbCache;    unsigned long ginstrs=0, tinstrs=0, gbytes = 0, tbytes=0;    /* Finish off the last BB */    M->curr_bb_entry->trans_bb_end_eip = (unsigned long) M->bbOut;    M->curr_bb_entry->flags |= IS_END_OF_TRACE;        /* No of actual BBs */    for(i=0; i<M->no_of_bbs; i++) {      bb_entry *curr = &M->bb_entry_nodes[i];      if(curr->trans_bb_eip != NOT_YET_TRANSLATED)	nactualbbs++;    }    /* BB Analysis */    unsigned long ilongest_bb = 0;    unsigned long ilongest_bb_len = 0;    double iavg_bb_len = 0;    double ibb_sd = 0;    unsigned long blongest_bb = 0;    unsigned long blongest_bb_len = 0;    unsigned long bavg_bb_len = 0;    double bbb_sd = 0;    for(i=0; i<M->no_of_bbs; i++) {      bb_entry *curr = &M->bb_entry_nodes[i];      if(curr->nInstr > ilongest_bb_len) {	ilongest_bb_len = curr->nInstr;	ilongest_bb = i;      }      iavg_bb_len += curr->nInstr;    }    iavg_bb_len /= nactualbbs;    for(i=0; i<M->no_of_bbs; i++) {      bb_entry *curr = &M->bb_entry_nodes[i];      ibb_sd += ((double)curr->nInstr - iavg_bb_len) * ((double)curr->nInstr - iavg_bb_len);    }    ibb_sd /= nactualbbs;    ibb_sd = sqrt(ibb_sd);        /* Trace Analysis */    unsigned long longest_trace_len = 0;    unsigned long longest_trace_ilen = 0;    unsigned long longest_trace_start_bb = 0;    unsigned long longest_trace_bytes = 0;    double avg_trace = 0;    double avg_itrace = 0;        double avg_trbytes = 0;    double sd_trace = 0;    double sd_itrace = 0;    double sd_trbytes = 0;    unsigned long ntraces = 0;    for(i=0; i<M->no_of_bbs; i++) {      bb_entry *curr = &M->bb_entry_nodes[i];      curr->flags &= ~MARKED;     }        for(i=0; i<M->no_of_bbs; i++) {      bb_entry *curr = &M->bb_entry_nodes[i];       unsigned long trace_len=0;      unsigned long trace_instrs=0;      unsigned long trace_bytes = 0;      if(curr->flags & MARKED)	continue;      ntraces++;      while((curr != NULL) && (curr->trans_bb_eip != NOT_YET_TRANSLATED)) {	if(curr->flags & MARKED) {	  //fprintf(DBG, "@@MARKED in Trace\n");	}	else	  curr->flags |= MARKED;	trace_len++;	trace_instrs += curr->nInstr;	trace_bytes += curr->trans_bb_end_eip - curr->trans_bb_eip;	curr = curr->trace_next;      }      if(trace_len > longest_trace_len) {	longest_trace_len = trace_len;	longest_trace_ilen = trace_instrs;	longest_trace_start_bb = i;	longest_trace_bytes = trace_bytes;      }      avg_trace += trace_len;      avg_itrace += trace_instrs;      avg_trbytes += trace_bytes;    }    avg_trace /= ntraces;    avg_itrace /= ntraces;    avg_trbytes /= ntraces;        /* Now calculate SD */    for(i=0; i<M->no_of_bbs; i++) {      bb_entry *curr = &M->bb_entry_nodes[i];      curr->flags &= ~MARKED;     }    for(i=0; i<M->no_of_bbs; i++) {      bb_entry *curr = &M->bb_entry_nodes[i];       unsigned long trace_len=0;      unsigned long trace_bytes = 0;      if(curr->flags & MARKED)	continue;      while((curr != NULL) && (curr->trans_bb_eip != NOT_YET_TRANSLATED)) {	if(curr->flags & MARKED) {	  //fprintf(DBG, "##MARKED in Trace\n");	}	else	  curr->flags |= MARKED;	trace_len++;	trace_bytes += curr->trans_bb_end_eip - curr->trans_bb_eip;	curr = curr->trace_next;      }      sd_trace += (trace_len - avg_trace) * (trace_len - avg_trace);      sd_trbytes += (trace_bytes - avg_trbytes) * (trace_bytes - avg_trbytes);    }    sd_trace /= ntraces; sd_trace = sqrt(sd_trace);    sd_trbytes /= ntraces; sd_trbytes = sqrt(sd_trbytes);        /* No. of BBs needing Relocation */    for(i=0; i<M->no_of_bbs; i++) {      bb_entry *curr = &M->bb_entry_nodes[i];      if((curr->trans_bb_eip != NOT_YET_TRANSLATED) && (curr->flags & NEEDS_RELOC)) {	nrelocbbs++;	nrelocbytes += curr->trans_bb_end_eip - curr->trans_bb_eip;      }    }    /* Propagate the RELOC Flag Forward and backward */    for(i=0; i<M->no_of_bbs; i++) {      bb_entry *curr = &M->bb_entry_nodes[i];      bool reloc = false;      while((curr != NULL) && (curr->trans_bb_eip != NOT_YET_TRANSLATED)) {	if(curr->flags & NEEDS_RELOC) {	  reloc = true;	  break;	}	curr = curr->trace_next;      }      if(reloc) {	curr = &M->bb_entry_nodes[i];	while((curr != NULL) && (curr->trans_bb_eip != NOT_YET_TRANSLATED)) {	  curr->flags |= NEEDS_RELOC;	  curr = curr->trace_next;	  	}      }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -