1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- An example Valgrind tool. lk_main.c ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Lackey, an example Valgrind tool that does 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown some simple program measurement and tracing. 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Copyright (C) 2002-2011 Nicholas Nethercote 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown njn@valgrind.org 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This tool shows how to do some basic instrumentation. 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// There are four kinds of instrumentation it can do. They can be turned 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// on/off independently with command line options: 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// * --basic-counts : do basic counts, eg. number of instructions 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// executed, jumps executed, etc. 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// * --detailed-counts: do more detailed counts: number of loads, stores 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// and ALU operations of different sizes. 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// * --trace-mem=yes: trace all (data) memory accesses. 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// * --trace-superblocks=yes: 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// trace all superblock entries. Mostly of interest 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// to the Valgrind developers. 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The code for each kind of instrumentation is guarded by a clo_* variable: 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// clo_basic_counts, clo_detailed_counts, clo_trace_mem and clo_trace_sbs. 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// If you want to modify any of the instrumentation code, look for the code 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// that is guarded by the relevant clo_* variable (eg. clo_trace_mem) 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// If you're not interested in the other kinds of instrumentation you can 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// remove them. If you want to do more complex modifications, please read 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// VEX/pub/libvex_ir.h to understand the intermediate representation. 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Specific Details about --trace-mem=yes 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// -------------------------------------- 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Lackey's --trace-mem code is a good starting point for building Valgrind 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// tools that act on memory loads and stores. It also could be used as is, 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// with its output used as input to a post-mortem processing step. However, 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// because memory traces can be very large, online analysis is generally 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// better. 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// It prints memory data access traces that look like this: 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// I 0023C790,2 # instruction read at 0x0023C790 of size 2 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// I 0023C792,5 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// S BE80199C,4 # data store at 0xBE80199C of size 4 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// I 0025242B,3 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// L BE801950,4 # data load at 0xBE801950 of size 4 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// I 0023D476,7 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// M 0025747C,1 # data modify at 0x0025747C of size 1 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// I 0023DC20,2 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// L 00254962,1 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// L BE801FB3,1 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// I 00252305,1 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// L 00254AEB,1 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// S 00257998,1 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Every instruction executed has an "instr" event representing it. 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Instructions that do memory accesses are followed by one or more "load", 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// "store" or "modify" events. Some instructions do more than one load or 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// store, as in the last two examples in the above trace. 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Here are some examples of x86 instructions that do different combinations 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// of loads, stores, and modifies. 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Instruction Memory accesses Event sequence 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// ----------- --------------- -------------- 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// add %eax, %ebx No loads or stores instr 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// movl (%eax), %ebx loads (%eax) instr, load 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// movl %eax, (%ebx) stores (%ebx) instr, store 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// incl (%ecx) modifies (%ecx) instr, modify 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// cmpsb loads (%esi), loads(%edi) instr, load, load 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// call*l (%edx) loads (%edx), stores -4(%esp) instr, load, store 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// pushl (%edx) loads (%edx), stores -4(%esp) instr, load, store 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// movsw loads (%esi), stores (%edi) instr, load, store 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Instructions using x86 "rep" prefixes are traced as if they are repeated 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// N times. 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Lackey with --trace-mem gives good traces, but they are not perfect, for 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// the following reasons: 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - It does not trace into the OS kernel, so system calls and other kernel 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// operations (eg. some scheduling and signal handling code) are ignored. 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - It could model loads and stores done at the system call boundary using 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// the pre_mem_read/post_mem_write events. For example, if you call 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// fstat() you know that the passed in buffer has been written. But it 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// currently does not do this. 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - Valgrind replaces some code (not much) with its own, notably parts of 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// code for scheduling operations and signal handling. This code is not 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// traced. 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - There is no consideration of virtual-to-physical address mapping. 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This may not matter for many purposes. 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - Valgrind modifies the instruction stream in some very minor ways. For 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// example, on x86 the bts, btc, btr instructions are incorrectly 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// considered to always touch memory (this is a consequence of these 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// instructions being very difficult to simulate). 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - Valgrind tools layout memory differently to normal programs, so the 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// addresses you get will not be typical. Thus Lackey (and all Valgrind 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// tools) is suitable for getting relative memory traces -- eg. if you 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// want to analyse locality of memory accesses -- but is not good if 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// absolute addresses are important. 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Despite all these warnings, Lackey's results should be good enough for a 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// wide range of purposes. For example, Cachegrind shares all the above 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// shortcomings and it is still useful. 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// For further inspiration, you should look at cachegrind/cg_main.c which 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// uses the same basic technique for tracing memory accesses, but also groups 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// events together for processing into twos and threes so that fewer C calls 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// are made and things run faster. 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Specific Details about --trace-superblocks=yes 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// ---------------------------------------------- 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Valgrind splits code up into single entry, multiple exit blocks 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// known as superblocks. By itself, --trace-superblocks=yes just 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// prints a message as each superblock is run: 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// SB 04013170 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// SB 04013177 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// SB 04013173 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// SB 04013177 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The hex number is the address of the first instruction in the 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// superblock. You can see the relationship more obviously if you use 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// --trace-superblocks=yes and --trace-mem=yes together. Then a "SB" 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// message at address X is immediately followed by an "instr:" message 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// for that address, as the first instruction in the block is 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// executed, for example: 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// SB 04014073 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// I 04014073,3 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// L 7FEFFF7F8,8 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// I 04014076,4 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// I 0401407A,3 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// I 0401407D,3 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// I 04014080,3 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// I 04014083,6 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_basics.h" 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_tooliface.h" 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcassert.h" 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcprint.h" 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_debuginfo.h" 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcbase.h" 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_options.h" 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_machine.h" // VG_(fnptr_to_fnentry) 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Command line options ---*/ 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Command line options controlling instrumentation kinds, as described at 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the top of this file. */ 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool clo_basic_counts = True; 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool clo_detailed_counts = False; 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool clo_trace_mem = False; 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool clo_trace_sbs = False; 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The name of the function of which the number of calls (under 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * --basic-counts=yes) is to be counted, with default. Override with command 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * line option --fnname. */ 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Char* clo_fnname = "main"; 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool lk_process_cmd_line_option(Char* arg) 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if VG_STR_CLO(arg, "--fnname", clo_fnname) {} 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if VG_BOOL_CLO(arg, "--basic-counts", clo_basic_counts) {} 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if VG_BOOL_CLO(arg, "--detailed-counts", clo_detailed_counts) {} 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if VG_BOOL_CLO(arg, "--trace-mem", clo_trace_mem) {} 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if VG_BOOL_CLO(arg, "--trace-superblocks", clo_trace_sbs) {} 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(clo_fnname); 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(clo_fnname[0]); 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void lk_print_usage(void) 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" --basic-counts=no|yes count instructions, jumps, etc. [yes]\n" 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" --detailed-counts=no|yes count loads, stores and alu ops [no]\n" 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" --trace-mem=no|yes trace all loads and stores [no]\n" 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" --trace-superblocks=no|yes trace all superblock entries [no]\n" 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" --fnname=<name> count calls to <name> (only used if\n" 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" --basic-count=yes) [main]\n" 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void lk_print_debug_usage(void) 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" (none)\n" 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Stuff for --basic-counts ---*/ 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Nb: use ULongs because the numbers can get very big */ 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong n_func_calls = 0; 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong n_SBs_entered = 0; 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong n_SBs_completed = 0; 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong n_IRStmts = 0; 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong n_guest_instrs = 0; 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong n_Jccs = 0; 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong n_Jccs_untaken = 0; 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong n_IJccs = 0; 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong n_IJccs_untaken = 0; 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_one_func_call(void) 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_func_calls++; 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_one_SB_entered(void) 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_SBs_entered++; 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_one_SB_completed(void) 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_SBs_completed++; 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_one_IRStmt(void) 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_IRStmts++; 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_one_guest_instr(void) 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_guest_instrs++; 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_one_Jcc(void) 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_Jccs++; 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_one_Jcc_untaken(void) 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_Jccs_untaken++; 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_one_inverted_Jcc(void) 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_IJccs++; 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_one_inverted_Jcc_untaken(void) 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_IJccs_untaken++; 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Stuff for --detailed-counts ---*/ 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- Operations --- */ 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef enum { OpLoad=0, OpStore=1, OpAlu=2 } Op; 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_OPS 3 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- Types --- */ 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 304b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define N_TYPES 10 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int type2index ( IRType ty ) 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (ty) { 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I1: return 0; 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I8: return 1; 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I16: return 2; 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I32: return 3; 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I64: return 4; 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I128: return 5; 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_F32: return 6; 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_F64: return 7; 317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Ity_F128: return 8; 318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Ity_V128: return 9; 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: tl_assert(0); 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* nameOfTypeIndex ( Int i ) 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (i) { 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0: return "I1"; break; 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 1: return "I8"; break; 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 2: return "I16"; break; 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 3: return "I32"; break; 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 4: return "I64"; break; 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 5: return "I128"; break; 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 6: return "F32"; break; 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 7: return "F64"; break; 334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case 8: return "F128"; break; 335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case 9: return "V128"; break; 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: tl_assert(0); 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- Counts --- */ 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong detailCounts[N_OPS][N_TYPES]; 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The helper that is called from the instrumented code. */ 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(1) 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid increment_detail(ULong* detail) 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (*detail)++; 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A helper that adds the instrumentation for a detail. */ 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void instrument_detail(IRSB* sb, Op op, IRType type) 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRDirty* di; 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr** argv; 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const UInt typeIx = type2index(type); 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(op < N_OPS); 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(typeIx < N_TYPES); 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv = mkIRExprVec_1( mkIRExpr_HWord( (HWord)&detailCounts[op][typeIx] ) ); 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = unsafeIRDirty_0_N( 1, "increment_detail", 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( &increment_detail ), 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv); 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sb, IRStmt_Dirty(di) ); 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Summarize and print the details. */ 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void print_details ( void ) 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int typeIx; 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" Type Loads Stores AluOps\n"); 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" -------------------------------------------\n"); 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (typeIx = 0; typeIx < N_TYPES; typeIx++) { 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" %4s %'12llu %'12llu %'12llu\n", 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nameOfTypeIndex( typeIx ), 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown detailCounts[OpLoad ][typeIx], 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown detailCounts[OpStore][typeIx], 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown detailCounts[OpAlu ][typeIx] 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Stuff for --trace-mem ---*/ 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MAX_DSIZE 512 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRAtom; 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown enum { Event_Ir, Event_Dr, Event_Dw, Event_Dm } 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown EventKind; 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown EventKind ekind; 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRAtom* addr; 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int size; 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Event; 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Up to this many unnotified events are allowed. Must be at least two, 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown so that reads and writes to the same address can be merged into a modify. 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Beyond that, larger numbers just potentially induce more spilling due to 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extending live ranges of address temporaries. */ 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_EVENTS 4 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Maintain an ordered list of memory events which are outstanding, in 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the sense that no IR has yet been generated to do the relevant 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helper calls. The SB is scanned top to bottom and memory events 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown are added to the end of the list, merging with the most recent 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown notified event where possible (Dw immediately following Dr and 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown having the same size and EA can be merged). 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This merging is done so that for architectures which have 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown load-op-store instructions (x86, amd64), the instr is treated as if 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it makes just one memory reference (a modify), rather than two (a 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown read followed by a write at the same address). 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown At various points the list will need to be flushed, that is, IR 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generated from it. That must happen before any possible exit from 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the block (the end, or an IRStmt_Exit). Flushing also takes place 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown when there is no space to add a new event. 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If we require the simulation statistics to be up to date with 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown respect to possible memory exceptions, then the list would have to 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be flushed before each memory reference. That's a pain so we don't 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bother. 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Flushing the list consists of walking it start to end and emitting 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instrumentation IR for each event, in the order in which they 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown appear. */ 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Event events[N_EVENTS]; 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int events_used = 0; 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(2) void trace_instr(Addr addr, SizeT size) 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("I %08lx,%lu\n", addr, size); 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(2) void trace_load(Addr addr, SizeT size) 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)(" L %08lx,%lu\n", addr, size); 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(2) void trace_store(Addr addr, SizeT size) 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)(" S %08lx,%lu\n", addr, size); 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(2) void trace_modify(Addr addr, SizeT size) 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)(" M %08lx,%lu\n", addr, size); 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void flushEvents(IRSB* sb) 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* helperName; 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* helperAddr; 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr** argv; 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRDirty* di; 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Event* ev; 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < events_used; i++) { 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ev = &events[i]; 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Decide on helper fn to call and args to pass it. 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (ev->ekind) { 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Event_Ir: helperName = "trace_instr"; 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperAddr = trace_instr; break; 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Event_Dr: helperName = "trace_load"; 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperAddr = trace_load; break; 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Event_Dw: helperName = "trace_store"; 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperAddr = trace_store; break; 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Event_Dm: helperName = "trace_modify"; 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperAddr = trace_modify; break; 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(0); 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Add the helper. 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv = mkIRExprVec_2( ev->addr, mkIRExpr_HWord( ev->size ) ); 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = unsafeIRDirty_0_N( /*regparms*/2, 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperName, VG_(fnptr_to_fnentry)( helperAddr ), 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv ); 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sb, IRStmt_Dirty(di) ); 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown events_used = 0; 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// WARNING: If you aren't interested in instruction reads, you can omit the 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// code that adds calls to trace_instr() in flushEvents(). However, you 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// must still call this function, addEvent_Ir() -- it is necessary to add 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// the Ir events to the events list so that merging of paired load/store 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// events into modify events works correctly. 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addEvent_Ir ( IRSB* sb, IRAtom* iaddr, UInt isize ) 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Event* evt; 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(clo_trace_mem); 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( (VG_MIN_INSTR_SZB <= isize && isize <= VG_MAX_INSTR_SZB) 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || VG_CLREQ_SZB == isize ); 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (events_used == N_EVENTS) 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown flushEvents(sb); 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(events_used >= 0 && events_used < N_EVENTS); 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt = &events[events_used]; 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->ekind = Event_Ir; 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->addr = iaddr; 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->size = isize; 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown events_used++; 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid addEvent_Dr ( IRSB* sb, IRAtom* daddr, Int dsize ) 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Event* evt; 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(clo_trace_mem); 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(isIRAtom(daddr)); 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(dsize >= 1 && dsize <= MAX_DSIZE); 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (events_used == N_EVENTS) 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown flushEvents(sb); 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(events_used >= 0 && events_used < N_EVENTS); 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt = &events[events_used]; 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->ekind = Event_Dr; 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->addr = daddr; 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->size = dsize; 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown events_used++; 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid addEvent_Dw ( IRSB* sb, IRAtom* daddr, Int dsize ) 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Event* lastEvt; 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Event* evt; 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(clo_trace_mem); 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(isIRAtom(daddr)); 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(dsize >= 1 && dsize <= MAX_DSIZE); 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Is it possible to merge this write with the preceding read? 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lastEvt = &events[events_used-1]; 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (events_used > 0 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && lastEvt->ekind == Event_Dr 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && lastEvt->size == dsize 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && eqIRAtom(lastEvt->addr, daddr)) 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lastEvt->ekind = Event_Dm; 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // No. Add as normal. 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (events_used == N_EVENTS) 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown flushEvents(sb); 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(events_used >= 0 && events_used < N_EVENTS); 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt = &events[events_used]; 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->ekind = Event_Dw; 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->size = dsize; 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->addr = daddr; 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown events_used++; 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Stuff for --trace-superblocks ---*/ 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void trace_superblock(Addr addr) 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("SB %08lx\n", addr); 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Basic tool functions ---*/ 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void lk_post_clo_init(void) 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int op, tyIx; 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_detailed_counts) { 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (op = 0; op < N_OPS; op++) 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (tyIx = 0; tyIx < N_TYPES; tyIx++) 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown detailCounts[op][tyIx] = 0; 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* lk_instrument ( VgCallbackClosure* closure, 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRSB* sbIn, 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestLayout* layout, 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestExtents* vge, 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType gWordTy, IRType hWordTy ) 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRDirty* di; 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRSB* sbOut; 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char fnname[100]; 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType type; 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTypeEnv* tyenv = sbIn->tyenv; 614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr iaddr = 0, dst; 615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt ilen = 0; 616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool condition_inverted = False; 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (gWordTy != hWordTy) { 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We don't currently support this case. */ 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tool_panic)("host/guest word size mismatch"); 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set up SB */ 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sbOut = deepCopyIRSBExceptStmts(sbIn); 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Copy verbatim any IR preamble preceding the first IMark 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = 0; 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (i < sbIn->stmts_used && sbIn->stmts[i]->tag != Ist_IMark) { 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, sbIn->stmts[i] ); 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i++; 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_basic_counts) { 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Count this superblock. */ 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = unsafeIRDirty_0_N( 0, "add_one_SB_entered", 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( &add_one_SB_entered ), 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkIRExprVec_0() ); 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, IRStmt_Dirty(di) ); 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_trace_sbs) { 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Print this superblock's address. */ 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = unsafeIRDirty_0_N( 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, "trace_superblock", 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( &trace_superblock ), 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkIRExprVec_1( mkIRExpr_HWord( vge->base[0] ) ) 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, IRStmt_Dirty(di) ); 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_trace_mem) { 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown events_used = 0; 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (/*use current i*/; i < sbIn->stmts_used; i++) { 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt* st = sbIn->stmts[i]; 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!st || st->tag == Ist_NoOp) continue; 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_basic_counts) { 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Count one VEX statement. */ 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = unsafeIRDirty_0_N( 0, "add_one_IRStmt", 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( &add_one_IRStmt ), 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkIRExprVec_0() ); 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, IRStmt_Dirty(di) ); 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (st->tag) { 668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_NoOp: 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_AbiHint: 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_Put: 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_PutI: 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_MBE: 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, st ); 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_IMark: 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_basic_counts) { 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Needed to be able to check for inverted condition in Ist_Exit */ 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iaddr = st->Ist.IMark.addr; 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ilen = st->Ist.IMark.len; 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Count guest instruction. */ 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = unsafeIRDirty_0_N( 0, "add_one_guest_instr", 684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( &add_one_guest_instr ), 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkIRExprVec_0() ); 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, IRStmt_Dirty(di) ); 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* An unconditional branch to a known destination in the 689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * guest's instructions can be represented, in the IRSB to 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * instrument, by the VEX statements that are the 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * translation of that known destination. This feature is 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * called 'SB chasing' and can be influenced by command 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * line option --vex-guest-chase-thresh. 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * To get an accurate count of the calls to a specific 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * function, taking SB chasing into account, we need to 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * check for each guest instruction (Ist_IMark) if it is 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the entry point of a function. 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(clo_fnname); 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(clo_fnname[0]); 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(get_fnname_if_entry)(st->Ist.IMark.addr, 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fnname, sizeof(fnname)) 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && 0 == VG_(strcmp)(fnname, clo_fnname)) { 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = unsafeIRDirty_0_N( 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, "add_one_func_call", 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( &add_one_func_call ), 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkIRExprVec_0() ); 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, IRStmt_Dirty(di) ); 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_trace_mem) { 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // WARNING: do not remove this function call, even if you 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // aren't interested in instruction reads. See the comment 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // above the function itself for more detail. 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_Ir( sbOut, mkIRExpr_HWord( (HWord)st->Ist.IMark.addr ), 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st->Ist.IMark.len ); 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, st ); 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_WrTmp: 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Add a call to trace_load() if --trace-mem=yes. 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_trace_mem) { 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* data = st->Ist.WrTmp.data; 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (data->tag == Iex_Load) { 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_Dr( sbOut, data->Iex.Load.addr, 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeofIRType(data->Iex.Load.ty) ); 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_detailed_counts) { 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* expr = st->Ist.WrTmp.data; 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown type = typeOfIRExpr(sbOut->tyenv, expr); 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(type != Ity_INVALID); 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (expr->tag) { 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Load: 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instrument_detail( sbOut, OpLoad, type ); 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Unop: 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Binop: 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Triop: 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Qop: 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Mux0X: 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instrument_detail( sbOut, OpAlu, type ); 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, st ); 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_Store: 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_trace_mem) { 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* data = st->Ist.Store.data; 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_Dw( sbOut, st->Ist.Store.addr, 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeofIRType(typeOfIRExpr(tyenv, data)) ); 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_detailed_counts) { 760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown type = typeOfIRExpr(sbOut->tyenv, st->Ist.Store.data); 761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(type != Ity_INVALID); 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instrument_detail( sbOut, OpStore, type ); 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, st ); 765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_Dirty: { 768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_trace_mem) { 769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int dsize; 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRDirty* d = st->Ist.Dirty.details; 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d->mFx != Ifx_None) { 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // This dirty helper accesses memory. Collect the details. 773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(d->mAddr != NULL); 774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(d->mSize != 0); 775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dsize = d->mSize; 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_Dr( sbOut, d->mAddr, dsize ); 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_Dw( sbOut, d->mAddr, dsize ); 780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(d->mAddr == NULL); 782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(d->mSize == 0); 783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, st ); 786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_CAS: { 790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We treat it as a read and a write of the location. I 791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown think that is the same behaviour as it was before IRCAS 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown was introduced, since prior to that point, the Vex 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown front ends would translate a lock-prefixed instruction 794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown into a (normal) read followed by a (normal) write. */ 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int dataSize; 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType dataTy; 797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRCAS* cas = st->Ist.CAS.details; 798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(cas->addr != NULL); 799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(cas->dataLo != NULL); 800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dataTy = typeOfIRExpr(tyenv, cas->dataLo); 801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dataSize = sizeofIRType(dataTy); 802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (cas->dataHi != NULL) 803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dataSize *= 2; /* since it's a doubleword-CAS */ 804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_trace_mem) { 805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_Dr( sbOut, cas->addr, dataSize ); 806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_Dw( sbOut, cas->addr, dataSize ); 807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_detailed_counts) { 809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instrument_detail( sbOut, OpLoad, dataTy ); 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (cas->dataHi != NULL) /* dcas */ 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instrument_detail( sbOut, OpLoad, dataTy ); 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instrument_detail( sbOut, OpStore, dataTy ); 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (cas->dataHi != NULL) /* dcas */ 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instrument_detail( sbOut, OpStore, dataTy ); 815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, st ); 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_LLSC: { 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType dataTy; 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (st->Ist.LLSC.storedata == NULL) { 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* LL */ 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dataTy = typeOfIRTemp(tyenv, st->Ist.LLSC.result); 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_trace_mem) 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_Dr( sbOut, st->Ist.LLSC.addr, 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeofIRType(dataTy) ); 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_detailed_counts) 829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instrument_detail( sbOut, OpLoad, dataTy ); 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SC */ 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dataTy = typeOfIRExpr(tyenv, st->Ist.LLSC.storedata); 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_trace_mem) 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_Dw( sbOut, st->Ist.LLSC.addr, 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeofIRType(dataTy) ); 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_detailed_counts) 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instrument_detail( sbOut, OpStore, dataTy ); 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, st ); 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_Exit: 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_basic_counts) { 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // The condition of a branch was inverted by VEX if a taken 846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // branch is in fact a fall trough according to client address 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(iaddr != 0); 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst = (sizeof(Addr) == 4) ? st->Ist.Exit.dst->Ico.U32 : 849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st->Ist.Exit.dst->Ico.U64; 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown condition_inverted = (dst == iaddr + ilen); 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Count Jcc */ 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!condition_inverted) 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = unsafeIRDirty_0_N( 0, "add_one_Jcc", 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( &add_one_Jcc ), 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkIRExprVec_0() ); 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = unsafeIRDirty_0_N( 0, "add_one_inverted_Jcc", 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &add_one_inverted_Jcc ), 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkIRExprVec_0() ); 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, IRStmt_Dirty(di) ); 864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_trace_mem) { 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown flushEvents(sbOut); 867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, st ); // Original statement 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_basic_counts) { 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Count non-taken Jcc */ 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!condition_inverted) 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = unsafeIRDirty_0_N( 0, "add_one_Jcc_untaken", 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &add_one_Jcc_untaken ), 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkIRExprVec_0() ); 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = unsafeIRDirty_0_N( 0, "add_one_inverted_Jcc_untaken", 880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( 881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &add_one_inverted_Jcc_untaken ), 882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkIRExprVec_0() ); 883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, IRStmt_Dirty(di) ); 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(0); 890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_basic_counts) { 894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Count this basic block. */ 895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = unsafeIRDirty_0_N( 0, "add_one_SB_completed", 896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( &add_one_SB_completed ), 897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkIRExprVec_0() ); 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( sbOut, IRStmt_Dirty(di) ); 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_trace_mem) { 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* At the end of the sbIn. Flush outstandings. */ 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown flushEvents(sbOut); 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sbOut; 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void lk_fini(Int exitcode) 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 911b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char percentify_buf[5]; /* Two digits, '%' and 0. */ 912b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov const int percentify_size = sizeof(percentify_buf) - 1; 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const int percentify_decs = 0; 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(clo_fnname); 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(clo_fnname[0]); 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_basic_counts) { 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong total_Jccs = n_Jccs + n_IJccs; 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong taken_Jccs = (n_Jccs - n_Jccs_untaken) + n_IJccs_untaken; 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Counted %'llu call%s to %s()\n", 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_func_calls, ( n_func_calls==1 ? "" : "s" ), clo_fnname); 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("\n"); 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Jccs:\n"); 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" total: %'llu\n", total_Jccs); 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(percentify)(taken_Jccs, (total_Jccs ? total_Jccs : 1), 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown percentify_decs, percentify_size, percentify_buf); 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" taken: %'llu (%s)\n", 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown taken_Jccs, percentify_buf); 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("\n"); 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Executed:\n"); 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" SBs entered: %'llu\n", n_SBs_entered); 936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" SBs completed: %'llu\n", n_SBs_completed); 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" guest instrs: %'llu\n", n_guest_instrs); 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" IRStmts: %'llu\n", n_IRStmts); 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("\n"); 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Ratios:\n"); 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(n_SBs_entered); // Paranoia time. 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" guest instrs : SB entered = %'llu : 10\n", 944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 10 * n_guest_instrs / n_SBs_entered); 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" IRStmts : SB entered = %'llu : 10\n", 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 10 * n_IRStmts / n_SBs_entered); 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(n_guest_instrs); // Paranoia time. 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" IRStmts : guest instr = %'llu : 10\n", 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 10 * n_IRStmts / n_guest_instrs); 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_detailed_counts) { 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("\n"); 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("IR-level counts by type:\n"); 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown print_details(); 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clo_basic_counts) { 959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("\n"); 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Exit code: %d\n", exitcode); 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void lk_pre_clo_init(void) 965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_name) ("Lackey"); 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_version) (NULL); 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_description) ("an example Valgrind tool"); 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_copyright_author)( 970b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "Copyright (C) 2002-2011, and GNU GPL'd, by Nicholas Nethercote."); 971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_bug_reports_to) (VG_BUGS_TO); 972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_avg_translation_sizeB) ( 200 ); 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(basic_tool_funcs) (lk_post_clo_init, 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lk_instrument, 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lk_fini); 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(needs_command_line_options)(lk_process_cmd_line_option, 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lk_print_usage, 979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lk_print_debug_usage); 980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_DETERMINE_INTERFACE_VERSION(lk_pre_clo_init) 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end lk_main.c ---*/ 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 987