?? emit.c
字號:
/* * 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 + -