1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//--------------------------------------------------------------------*/ 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//--- BBV: a SimPoint basic block vector generator bbv_main.c ---*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//--------------------------------------------------------------------*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of BBV, a Valgrind tool for generating SimPoint 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown basic block vectors. 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 9b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Copyright (C) 2006-2011 Vince Weaver 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vince _at_ csl.cornell.edu 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 12b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov pcfile code is Copyright (C) 2006-2011 Oriol Prat 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown oriol.prat _at _ bsc.es 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_basics.h" 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_tooliface.h" 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_options.h" /* command line options */ 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_vki.h" /* vki_stat */ 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcbase.h" /* VG_(strlen) */ 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcfile.h" /* VG_(write) */ 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcprint.h" /* VG_(printf) */ 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcassert.h" /* VG_(exit) */ 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_mallocfree.h" /* plain_free */ 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_machine.h" /* VG_(fnptr_to_fnentry) */ 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_debuginfo.h" /* VG_(get_fnname) */ 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_oset.h" /* ordered set stuff */ 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* instruction special cases */ 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define REP_INSTRUCTION 0x1 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define FLDCW_INSTRUCTION 0x2 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* interval variables */ 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEFAULT_GRAIN_SIZE 100000000 /* 100 million by default */ 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int interval_size=DEFAULT_GRAIN_SIZE; 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* filenames */ 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar *clo_bb_out_file="bb.out.%p"; 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar *clo_pc_out_file="pc.out.%p"; 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar *pc_out_file=NULL; 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar *bb_out_file=NULL; 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* output parameters */ 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool instr_count_only=False; 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool generate_pc_file=False; 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* write buffer */ 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar buf[1024]; 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Global values */ 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic OSet* instr_info_table; /* table that holds the basic block info */ 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int block_num=1; /* global next block number */ 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int current_thread=0; 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int allocated_threads=1; 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct thread_info *bbv_thread=NULL; 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Per-thread variables */ 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct thread_info { 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong dyn_instr; /* Current retired instruction count */ 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong total_instr; /* Total retired instruction count */ 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr last_rep_addr; /* rep counting values */ 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong rep_count; 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong global_rep_count; 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong unique_rep_count; 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong fldcw_count; /* fldcw count */ 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int bbtrace_fd; /* file descriptor */ 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}; 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define FUNCTION_NAME_LENGTH 20 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct BB_info { 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr BB_addr; /* used as key, must be first */ 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int n_instrs; /* instructions in the basic block */ 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int block_num; /* unique block identifier */ 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int *inst_counter; /* times entered * num_instructions */ 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool is_entry; /* is this block a function entry point */ 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar fn_name[FUNCTION_NAME_LENGTH]; /* Function block is in */ 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}; 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* dump the optional PC file, which contains basic block number to */ 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* instruction address and function name mappings */ 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void dumpPcFile(void) 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct BB_info *bb_elem; 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int pctrace_fd; 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres; 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pc_out_file = 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(expand_file_name)("--pc-out-file", clo_pc_out_file); 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_(open)(pc_out_file, VKI_O_CREAT|VKI_O_TRUNC|VKI_O_WRONLY, 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_S_IRUSR|VKI_S_IWUSR|VKI_S_IRGRP|VKI_S_IWGRP); 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(sres)) { 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Error: cannot create pc file %s\n", pc_out_file); 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(exit)(1); 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pctrace_fd = sr_Res(sres); 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Loop through the table, printing the number, address, */ 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* and function name for each basic block */ 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetGen_ResetIter)(instr_info_table); 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( (bb_elem = VG_(OSetGen_Next)(instr_info_table)) ) { 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(write)(pctrace_fd,"F",1); 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)( buf,":%d:%x:%s\n", 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb_elem->block_num, 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)bb_elem->BB_addr, 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb_elem->fn_name); 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(write)(pctrace_fd, (void*)buf, VG_(strlen)(buf)); 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(close)(pctrace_fd); 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int open_tracefile(Int thread_num) 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres; 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar temp_string[2048]; 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For thread 1, don't append any thread number */ 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This lets the single-thread case not have any */ 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* extra values appended to the file name. */ 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (thread_num==1) { 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy)(temp_string,bb_out_file,2047); 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(temp_string,"%s.%d",bb_out_file,thread_num); 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_(open)(temp_string, VKI_O_CREAT|VKI_O_TRUNC|VKI_O_WRONLY, 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_S_IRUSR|VKI_S_IWUSR|VKI_S_IRGRP|VKI_S_IWGRP); 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(sres)) { 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Error: cannot create bb file %s\n",temp_string); 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(exit)(1); 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_Res(sres); 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void handle_overflow(void) 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct BB_info *bb_elem; 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bbv_thread[current_thread].dyn_instr > interval_size) { 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!instr_count_only) { 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If our output fd hasn't been opened, open it */ 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bbv_thread[current_thread].bbtrace_fd < 0) { 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[current_thread].bbtrace_fd=open_tracefile(current_thread); 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* put an entry to the bb.out file */ 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(write)(bbv_thread[current_thread].bbtrace_fd,"T",1); 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetGen_ResetIter)(instr_info_table); 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( (bb_elem = VG_(OSetGen_Next)(instr_info_table)) ) { 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( bb_elem->inst_counter[current_thread] != 0 ) { 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)( buf,":%d:%d ", 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb_elem->block_num, 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb_elem->inst_counter[current_thread]); 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(write)(bbv_thread[current_thread].bbtrace_fd, 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)buf, VG_(strlen)(buf)); 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb_elem->inst_counter[current_thread] = 0; 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(write)(bbv_thread[current_thread].bbtrace_fd,"\n",1); 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[current_thread].dyn_instr -= interval_size; 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void close_out_reps(void) 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[current_thread].global_rep_count+=bbv_thread[current_thread].rep_count; 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[current_thread].unique_rep_count++; 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[current_thread].rep_count=0; 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Generic function to get called each instruction */ 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(1) void per_instruction_BBV(struct BB_info *bbInfo) 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int n_instrs=1; 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(bbInfo); 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* we finished rep but didn't clear out count */ 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bbv_thread[current_thread].rep_count) { 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_instrs++; 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown close_out_reps(); 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbInfo->inst_counter[current_thread]+=n_instrs; 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[current_thread].total_instr+=n_instrs; 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[current_thread].dyn_instr +=n_instrs; 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handle_overflow(); 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Function to get called if instruction has a rep prefix */ 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(1) void per_instruction_BBV_rep(Addr addr) 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* handle back-to-back rep instructions */ 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bbv_thread[current_thread].last_rep_addr!=addr) { 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bbv_thread[current_thread].rep_count) { 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown close_out_reps(); 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[current_thread].total_instr++; 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[current_thread].dyn_instr++; 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[current_thread].last_rep_addr=addr; 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[current_thread].rep_count++; 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Function to call if our instruction has a fldcw instruction */ 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(1) void per_instruction_BBV_fldcw(struct BB_info *bbInfo) 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int n_instrs=1; 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(bbInfo); 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* we finished rep but didn't clear out count */ 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bbv_thread[current_thread].rep_count) { 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_instrs++; 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown close_out_reps(); 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* count fldcw instructions */ 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[current_thread].fldcw_count++; 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbInfo->inst_counter[current_thread]+=n_instrs; 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[current_thread].total_instr+=n_instrs; 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[current_thread].dyn_instr +=n_instrs; 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handle_overflow(); 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check if the instruction pointed to is one that needs */ 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* special handling. If so, set a bit in the return */ 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* value indicating what type. */ 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int get_inst_type(Int len, Addr addr) 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int result=0; 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGA_x86) || defined(VGA_amd64) 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned char *inst_pointer; 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned char inst_byte; 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int i,possible_rep; 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* rep prefixed instructions are counted as one instruction on */ 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* x86 processors and must be handled as a special case */ 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Also, the rep prefix is re-used as part of the opcode for */ 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SSE instructions. So we need to specifically check for */ 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* the following: movs, cmps, scas, lods, stos, ins, outs */ 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inst_pointer=(unsigned char *)addr; 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i=0; 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inst_byte=0; 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown possible_rep=0; 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (i<len) { 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inst_byte=*inst_pointer; 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( (inst_byte == 0x67) || /* size override prefix */ 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (inst_byte == 0x66) || /* size override prefix */ 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (inst_byte == 0x48) ) { /* 64-bit prefix */ 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if ( (inst_byte == 0xf2) || /* rep prefix */ 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (inst_byte == 0xf3) ) { /* repne prefix */ 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown possible_rep=1; 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; /* other byte, exit */ 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i++; 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inst_pointer++; 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( possible_rep && 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( ( (inst_byte >= 0xa4) && /* movs,cmps,scas */ 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (inst_byte <= 0xaf) ) || /* lods,stos */ 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( (inst_byte >= 0x6c) && 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (inst_byte <= 0x6f) ) ) ) { /* ins,outs */ 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown result|=REP_INSTRUCTION; 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* fldcw instructions are double-counted by the hardware */ 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* performance counters on pentium 4 processors so it is */ 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* useful to have that count when doing validation work. */ 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inst_pointer=(unsigned char *)addr; 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (len>1) { 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FLDCW detection */ 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* opcode is 0xd9/5, ie 1101 1001 oo10 1mmm */ 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((*inst_pointer==0xd9) && 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (*(inst_pointer+1)<0xb0) && /* need this case of fldz, etc, count */ 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( (*(inst_pointer+1) & 0x38) == 0x28)) { 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown result|=FLDCW_INSTRUCTION; 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return result; 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Our instrumentation function */ 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* sbIn = super block to translate */ 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* layout = guest layout */ 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* gWordTy = size of guest word */ 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* hWordTy = size of host word */ 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRSB* bbv_instrument ( VgCallbackClosure* closure, 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRSB* sbIn, VexGuestLayout* layout, 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestExtents* vge, 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType gWordTy, IRType hWordTy ) 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i,n_instrs=1; 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRSB *sbOut; 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt *st; 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct BB_info *bbInfo; 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr64 origAddr,ourAddr; 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRDirty *di; 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr **argv, *arg1; 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int regparms,opcode_type; 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We don't handle a host/guest word size mismatch */ 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (gWordTy != hWordTy) { 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tool_panic)("host/guest word size mismatch"); 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set up SB */ 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sbOut = deepCopyIRSBExceptStmts(sbIn); 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Copy verbatim any IR preamble preceding the first IMark */ 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = 0; 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( (i < sbIn->stmts_used) && (sbIn->stmts[i]->tag!=Ist_IMark)) { 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, sbIn->stmts[i] ); 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i++; 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Get the first statement */ 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(sbIn->stmts_used > 0); 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st = sbIn->stmts[i]; 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* double check we are at a Mark statement */ 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(Ist_IMark == st->tag); 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown origAddr=st->Ist.IMark.addr; 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Get the BB_info */ 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbInfo = VG_(OSetGen_Lookup)(instr_info_table, &origAddr); 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bbInfo==NULL) { 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* BB never translated before (at this address, at least; */ 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* could have been unloaded and then reloaded elsewhere in memory) */ 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* allocate and initialize a new basic block structure */ 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbInfo=VG_(OSetGen_AllocNode)(instr_info_table, sizeof(struct BB_info)); 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbInfo->BB_addr = origAddr; 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbInfo->n_instrs = n_instrs; 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbInfo->inst_counter=VG_(calloc)("bbv_instrument", 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allocated_threads, 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeof(Int)); 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* assign a unique block number */ 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbInfo->block_num=block_num; 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block_num++; 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* get function name and entry point information */ 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_fnname)(origAddr,bbInfo->fn_name,FUNCTION_NAME_LENGTH); 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbInfo->is_entry=VG_(get_fnname_if_entry)(origAddr, bbInfo->fn_name, 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown FUNCTION_NAME_LENGTH); 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* insert structure into table */ 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetGen_Insert)( instr_info_table, bbInfo ); 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Iterate through the basic block, putting the original */ 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* instructions in place, plus putting a call to updateBBV */ 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* for each original instruction */ 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This is less efficient than only instrumenting the BB */ 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* But it gives proper results given the fact that */ 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* valgrind uses superblocks (not basic blocks) by default */ 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while(i < sbIn->stmts_used) { 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st=sbIn->stmts[i]; 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (st->tag == Ist_IMark) { 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ourAddr = st->Ist.IMark.addr; 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown opcode_type=get_inst_type(st->Ist.IMark.len,ourAddr); 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regparms=1; 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg1= mkIRExpr_HWord( (HWord)bbInfo); 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv= mkIRExprVec_1(arg1); 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (opcode_type&REP_INSTRUCTION) { 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg1= mkIRExpr_HWord(ourAddr); 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv= mkIRExprVec_1(arg1); 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di= unsafeIRDirty_0_N( regparms, "per_instruction_BBV_rep", 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( &per_instruction_BBV_rep ), 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv); 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if (opcode_type&FLDCW_INSTRUCTION) { 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di= unsafeIRDirty_0_N( regparms, "per_instruction_BBV_fldcw", 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( &per_instruction_BBV_fldcw ), 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv); 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di= unsafeIRDirty_0_N( regparms, "per_instruction_BBV", 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( &per_instruction_BBV ), 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv); 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Insert our call */ 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, IRStmt_Dirty(di)); 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Insert the original instruction */ 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, st ); 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i++; 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sbOut; 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic struct thread_info *allocate_new_thread(struct thread_info *old, 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int old_number, Int new_number) 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct thread_info *temp; 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct BB_info *bb_elem; 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temp=VG_(realloc)("bbv_main.c allocate_threads", 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old, 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new_number*sizeof(struct thread_info)); 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* init the new thread */ 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We loop in case the new thread is not contiguous */ 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for(i=old_number;i<new_number;i++) { 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temp[i].last_rep_addr=0; 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temp[i].dyn_instr=0; 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temp[i].total_instr=0; 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temp[i].global_rep_count=0; 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temp[i].unique_rep_count=0; 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temp[i].rep_count=0; 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temp[i].fldcw_count=0; 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temp[i].bbtrace_fd=-1; 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* expand the inst_counter on all allocated basic blocks */ 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetGen_ResetIter)(instr_info_table); 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( (bb_elem = VG_(OSetGen_Next)(instr_info_table)) ) { 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb_elem->inst_counter = 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(realloc)("bbv_main.c inst_counter", 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb_elem->inst_counter, 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new_number*sizeof(Int)); 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for(i=old_number;i<new_number;i++) { 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb_elem->inst_counter[i]=0; 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return temp; 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void bbv_thread_called ( ThreadId tid, ULong nDisp ) 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tid >= allocated_threads) { 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread=allocate_new_thread(bbv_thread,allocated_threads,tid+1); 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allocated_threads=tid+1; 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown current_thread=tid; 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Setup ---*/ 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void bbv_post_clo_init(void) 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb_out_file = 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(expand_file_name)("--bb-out-file", clo_bb_out_file); 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Try a closer approximation of basic blocks */ 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This is the same as the command line option */ 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --vex-guest-chase-thresh=0 */ 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(clo_vex_control).guest_chase_thresh = 0; 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Parse the command line options */ 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool bbv_process_cmd_line_option(Char* arg) 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if VG_INT_CLO (arg, "--interval-size", interval_size) {} 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if VG_STR_CLO (arg, "--bb-out-file", clo_bb_out_file) {} 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if VG_STR_CLO (arg, "--pc-out-file", clo_pc_out_file) { 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generate_pc_file = True; 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if VG_BOOL_CLO (arg, "--instr-count-only", instr_count_only) {} 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void bbv_print_usage(void) 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" --bb-out-file=<file> filename for BBV info\n" 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" --pc-out-file=<file> filename for BB addresses and function names\n" 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" --interval-size=<num> interval size\n" 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" --instr-count-only=yes|no only print total instruction count\n" 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void bbv_print_debug_usage(void) 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)(" (none)\n"); 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void bbv_fini(Int exitcode) 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (generate_pc_file) { 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dumpPcFile(); 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for(i=0;i<allocated_threads;i++) { 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bbv_thread[i].total_instr!=0) { 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf,"\n\n" 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "# Thread %d\n" 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "# Total intervals: %d (Interval Size %d)\n" 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "# Total instructions: %lld\n" 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "# Total reps: %lld\n" 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "# Unique reps: %lld\n" 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "# Total fldcw instructions: %lld\n\n", 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i, 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)(bbv_thread[i].total_instr/(ULong)interval_size), 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown interval_size, 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[i].total_instr, 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[i].global_rep_count, 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[i].unique_rep_count, 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[i].fldcw_count); 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Print results to display */ 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("%s\n", buf); 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* open the output file if it hasn't already */ 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bbv_thread[i].bbtrace_fd < 0) { 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[i].bbtrace_fd=open_tracefile(i); 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Also print to results file */ 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(write)(bbv_thread[i].bbtrace_fd,(void*)buf,VG_(strlen)(buf)); 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(close)(bbv_thread[i].bbtrace_fd); 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void bbv_pre_clo_init(void) 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_name) ("exp-bbv"); 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_version) (NULL); 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_description) ("a SimPoint basic block vector generator"); 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_copyright_author)( 610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "Copyright (C) 2006-2011 Vince Weaver"); 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_bug_reports_to) (VG_BUGS_TO); 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(basic_tool_funcs) (bbv_post_clo_init, 614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_instrument, 615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_fini); 616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(needs_command_line_options)(bbv_process_cmd_line_option, 618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_print_usage, 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_print_debug_usage); 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(track_start_client_code)( bbv_thread_called ); 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instr_info_table = VG_(OSetGen_Create)(/*keyOff*/0, 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL, 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(malloc), "bbv.1", VG_(free)); 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread=allocate_new_thread(bbv_thread,0,allocated_threads); 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_DETERMINE_INTERFACE_VERSION(bbv_pre_clo_init) 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 636