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 9436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Copyright (C) 2006-2013 Vince Weaver 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vince _at_ csl.cornell.edu 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 12436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov pcfile code is Copyright (C) 2006-2013 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 */ 58436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic const HChar *clo_bb_out_file="bb.out.%p"; 59436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic const HChar *clo_pc_out_file="pc.out.%p"; 60436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic HChar *pc_out_file=NULL; 61436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic HChar *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 */ 69436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic HChar 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 */ 98436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar 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; 140436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar 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 278436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UChar *inst_pointer; 279436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UChar 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 289436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov inst_pointer=(UChar *)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 325436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov inst_pointer=(UChar *)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, 350436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VexArchInfo* archinfo_host, 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType gWordTy, IRType hWordTy ) 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i,n_instrs=1; 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRSB *sbOut; 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt *st; 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct BB_info *bbInfo; 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr64 origAddr,ourAddr; 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRDirty *di; 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr **argv, *arg1; 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int regparms,opcode_type; 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We don't handle a host/guest word size mismatch */ 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (gWordTy != hWordTy) { 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tool_panic)("host/guest word size mismatch"); 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set up SB */ 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sbOut = deepCopyIRSBExceptStmts(sbIn); 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Copy verbatim any IR preamble preceding the first IMark */ 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = 0; 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( (i < sbIn->stmts_used) && (sbIn->stmts[i]->tag!=Ist_IMark)) { 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, sbIn->stmts[i] ); 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i++; 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Get the first statement */ 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(sbIn->stmts_used > 0); 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st = sbIn->stmts[i]; 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* double check we are at a Mark statement */ 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(Ist_IMark == st->tag); 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown origAddr=st->Ist.IMark.addr; 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Get the BB_info */ 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbInfo = VG_(OSetGen_Lookup)(instr_info_table, &origAddr); 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bbInfo==NULL) { 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* BB never translated before (at this address, at least; */ 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* could have been unloaded and then reloaded elsewhere in memory) */ 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* allocate and initialize a new basic block structure */ 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbInfo=VG_(OSetGen_AllocNode)(instr_info_table, sizeof(struct BB_info)); 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbInfo->BB_addr = origAddr; 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbInfo->n_instrs = n_instrs; 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbInfo->inst_counter=VG_(calloc)("bbv_instrument", 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allocated_threads, 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeof(Int)); 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* assign a unique block number */ 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbInfo->block_num=block_num; 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block_num++; 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* get function name and entry point information */ 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_fnname)(origAddr,bbInfo->fn_name,FUNCTION_NAME_LENGTH); 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbInfo->is_entry=VG_(get_fnname_if_entry)(origAddr, bbInfo->fn_name, 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown FUNCTION_NAME_LENGTH); 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* insert structure into table */ 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetGen_Insert)( instr_info_table, bbInfo ); 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Iterate through the basic block, putting the original */ 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* instructions in place, plus putting a call to updateBBV */ 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* for each original instruction */ 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This is less efficient than only instrumenting the BB */ 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* But it gives proper results given the fact that */ 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* valgrind uses superblocks (not basic blocks) by default */ 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while(i < sbIn->stmts_used) { 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st=sbIn->stmts[i]; 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (st->tag == Ist_IMark) { 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ourAddr = st->Ist.IMark.addr; 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown opcode_type=get_inst_type(st->Ist.IMark.len,ourAddr); 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regparms=1; 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg1= mkIRExpr_HWord( (HWord)bbInfo); 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv= mkIRExprVec_1(arg1); 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (opcode_type&REP_INSTRUCTION) { 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg1= mkIRExpr_HWord(ourAddr); 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv= mkIRExprVec_1(arg1); 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di= unsafeIRDirty_0_N( regparms, "per_instruction_BBV_rep", 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( &per_instruction_BBV_rep ), 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv); 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if (opcode_type&FLDCW_INSTRUCTION) { 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di= unsafeIRDirty_0_N( regparms, "per_instruction_BBV_fldcw", 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( &per_instruction_BBV_fldcw ), 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv); 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di= unsafeIRDirty_0_N( regparms, "per_instruction_BBV", 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( &per_instruction_BBV ), 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv); 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Insert our call */ 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, IRStmt_Dirty(di)); 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Insert the original instruction */ 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, st ); 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i++; 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sbOut; 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic struct thread_info *allocate_new_thread(struct thread_info *old, 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int old_number, Int new_number) 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct thread_info *temp; 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct BB_info *bb_elem; 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temp=VG_(realloc)("bbv_main.c allocate_threads", 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old, 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new_number*sizeof(struct thread_info)); 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* init the new thread */ 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We loop in case the new thread is not contiguous */ 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for(i=old_number;i<new_number;i++) { 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temp[i].last_rep_addr=0; 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temp[i].dyn_instr=0; 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temp[i].total_instr=0; 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temp[i].global_rep_count=0; 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temp[i].unique_rep_count=0; 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temp[i].rep_count=0; 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temp[i].fldcw_count=0; 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temp[i].bbtrace_fd=-1; 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* expand the inst_counter on all allocated basic blocks */ 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetGen_ResetIter)(instr_info_table); 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( (bb_elem = VG_(OSetGen_Next)(instr_info_table)) ) { 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb_elem->inst_counter = 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(realloc)("bbv_main.c inst_counter", 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb_elem->inst_counter, 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new_number*sizeof(Int)); 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for(i=old_number;i<new_number;i++) { 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb_elem->inst_counter[i]=0; 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return temp; 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void bbv_thread_called ( ThreadId tid, ULong nDisp ) 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tid >= allocated_threads) { 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread=allocate_new_thread(bbv_thread,allocated_threads,tid+1); 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allocated_threads=tid+1; 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown current_thread=tid; 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Setup ---*/ 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void bbv_post_clo_init(void) 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb_out_file = 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(expand_file_name)("--bb-out-file", clo_bb_out_file); 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Try a closer approximation of basic blocks */ 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This is the same as the command line option */ 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --vex-guest-chase-thresh=0 */ 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(clo_vex_control).guest_chase_thresh = 0; 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Parse the command line options */ 534436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool bbv_process_cmd_line_option(const HChar* arg) 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if VG_INT_CLO (arg, "--interval-size", interval_size) {} 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if VG_STR_CLO (arg, "--bb-out-file", clo_bb_out_file) {} 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if VG_STR_CLO (arg, "--pc-out-file", clo_pc_out_file) { 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generate_pc_file = True; 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if VG_BOOL_CLO (arg, "--instr-count-only", instr_count_only) {} 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void bbv_print_usage(void) 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" --bb-out-file=<file> filename for BBV info\n" 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" --pc-out-file=<file> filename for BB addresses and function names\n" 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" --interval-size=<num> interval size\n" 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" --instr-count-only=yes|no only print total instruction count\n" 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void bbv_print_debug_usage(void) 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)(" (none)\n"); 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void bbv_fini(Int exitcode) 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (generate_pc_file) { 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dumpPcFile(); 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for(i=0;i<allocated_threads;i++) { 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bbv_thread[i].total_instr!=0) { 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf,"\n\n" 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "# Thread %d\n" 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "# Total intervals: %d (Interval Size %d)\n" 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "# Total instructions: %lld\n" 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "# Total reps: %lld\n" 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "# Unique reps: %lld\n" 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "# Total fldcw instructions: %lld\n\n", 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i, 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)(bbv_thread[i].total_instr/(ULong)interval_size), 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown interval_size, 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[i].total_instr, 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[i].global_rep_count, 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[i].unique_rep_count, 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[i].fldcw_count); 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Print results to display */ 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("%s\n", buf); 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* open the output file if it hasn't already */ 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bbv_thread[i].bbtrace_fd < 0) { 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread[i].bbtrace_fd=open_tracefile(i); 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Also print to results file */ 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(write)(bbv_thread[i].bbtrace_fd,(void*)buf,VG_(strlen)(buf)); 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(close)(bbv_thread[i].bbtrace_fd); 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void bbv_pre_clo_init(void) 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_name) ("exp-bbv"); 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_version) (NULL); 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_description) ("a SimPoint basic block vector generator"); 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_copyright_author)( 611436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "Copyright (C) 2006-2013 Vince Weaver"); 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_bug_reports_to) (VG_BUGS_TO); 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(basic_tool_funcs) (bbv_post_clo_init, 615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_instrument, 616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_fini); 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(needs_command_line_options)(bbv_process_cmd_line_option, 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_print_usage, 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_print_debug_usage); 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(track_start_client_code)( bbv_thread_called ); 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instr_info_table = VG_(OSetGen_Create)(/*keyOff*/0, 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL, 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(malloc), "bbv.1", VG_(free)); 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbv_thread=allocate_new_thread(bbv_thread,0,allocated_threads); 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_DETERMINE_INTERFACE_VERSION(bbv_pre_clo_init) 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 637