Install
- Make a tutorial directory such as:
~/tutorial/
-
Install dependencies: Pin and other packages (see download section)
- Pin installation will provide you a pin directory
-
Uncompress and untar archives:
tar -xvfz Pilp5.tar.gz
tar -xvfz Ilptool.tar.gz
-
Now, you have some known directories:
~/tutorial/pin-2.12-54730-gcc.4.4.7-linux/
(called pin directory)~/tutorial/Pilp5/
(called Pilp5 directory)~/tutorial/Ilptool/
(called Ilptool directory)
-
Build Pilp5 tool:
-
Go into Pilp5 directory, edit makefile and set appropriate PIN variables with full path such as example below:
PIN_HOME = /home/dparello/tutorial/pin-2.12-54730-gcc.4.4.7-linux PIN_ROOT = /home/dparello/tutorial/pin-2.12-54730-gcc.4.4.7-linux PIN_KIT = /home/dparello/tutorial/pin-2.12-54730-gcc.4.4.7-linux
-
Build the tool:
make
-
Go into Pilp5 directory, edit makefile and set appropriate PIN variables with full path such as example below:
-
Warning:
-
On systems running
yama
security kernel module, you have to run the following command as root to enable Pin:echo 0 > /proc/sys/kernel/yama/ptrace_scope
- As pin binary is a 32-bits binary, you have to install some 32-bits libraries on x86 64-bits operating systems.
-
On systems running
Getting started
Ilptool setup
- Go into
Ilptool
directory and launchILPManager.py
- Let
ILPManager.py
create some directories into your home. - Open
Preferences
,Change
and set approprite PIN path (Pin directory) and PIN Tool path (pintool directory) as shown below:

Example 1 (source code: ex1.tar.gz)
- Uncompress, untar archive.
- Go into
ex1
directory and run make../ex1/src/ex1.c
:#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <string.h> #include <unistd.h> void print_usage(char *s) { fprintf(stderr, "%s data_file\n", s); } double Sum(double *p, unsigned int n) { double r = p[0]; int i; for(i=1; i<n; i++) r += p[i]; return(r); } int main(int argc, char **argv) { unsigned int l; //taille vecteur somme double *x, Cact; //vecteur somme, son cond effectif int delta_act; // delta effectif double *x0; double r0=0.0; int r; if (argc<2) print_usage("ex1"); int file = open(argv[1], O_RDONLY); if (file == -1) {printf("erreur ouverture data_file\n"); exit(1);} r = read(file, &l, sizeof(unsigned int)); if (r!=sizeof(unsigned int)) {printf("erreur lecture data_file\n"); exit(1);} r = read(file, &Cact, sizeof(double)); if (r!=sizeof(double)) {printf("erreur lecture data_file\n"); exit(1);} r = read(file, &delta_act, sizeof(int)); if (r!=sizeof(int)) {printf("erreur lecture data_file\n"); exit(1);} x = (double *) malloc(sizeof(double)*l); for (int i=0; i<l; i++) { r = read(file, &x[i], sizeof(double)); if(r != sizeof(double)) { printf("erreur lecture data_file, arg num=%i\n", i); exit(1); } } close(file); x0 = malloc(sizeof(double)*l); memcpy(x0, x, sizeof(double)*l); r0 = Sum(x0, l); printf("%i \t %e \t %i \t ", l, Cact, delta_act); printf("\n"); printf("Sum %.16e\n", r0); return 0; }
- Into ILPManager.py, create a new project, edit it and set appropriate project name, directory, binary and arguments as shown below:

Setp 1: Getting simple Profile
- Into ILPManager, launch profiling (
Prof
) - Into ILPManager, select view profile (
ViewProf
) - The profile give you the
Global ILP
with number of instructions (I
), number of cycles (C
) and the resulting ILP as shown below:

Setp 2: Getting detailed Profile
- Edit project and set
depth
to -1 (maximal depth) - Into ILPManager, launch profiling (
Prof
) - Into ILPManager, select view profile (
ViewProf
) - The profile give you the call graph with
ILP
information for each call as shown below: -
-
Notes:
- Each call is enclosed by a
start
andstop
. - Detailed profile give you the function name and a unique call id. number provide by Pilp5 tool (
cid
).
- Each call is enclosed by a
Setp 3: Getting Histogram
- Launch histogram build (
Histo
) - Select view histogram (
ViewHisto
) select the file with function name and call id you want to analyse - For example, below the histogram of the call to
Sum
function:
Setp 4: Getting Dependency graph (Trace)
- Launch trace build (
Trace
) - Select view trace (
ViewTraceA
) select the file with function name and call id you want to analyse - For example, below is the trace of the call to
Sum
function: - Figure below, show a zoom on the beginning of the graph:


Other Examples (source code: extra-perpi.tar.gz)
Pilp5 internals
Pilp5 direct address
Setp 1: Getting detailed Profile
- Let's assume we know the pin_directory and the pilp5_directory
- Go into
ex1
directory - Create a directory name
perpi
to store all Pilp5 outputs - Copy the following xml code into a file named
_ilptool_command.xml
and set appropriateresdir
full path./_ilptool_command.xml
:<ilpcommand> <command>profile</command> <resdir>/home/dparello/tutorial/ex1/perpi/</resdir> <inst_control>all</inst_control> <dump_control>main</dump_control> <depth>-1</depth> <length>0</length> <floatonly>0</floatonly> </ilpcommand>
- The pin command has the following syntaxe:
PIN syntax
:pin [OPTION] [-t <tool> [<toolargs>]] -- <command line>
- Easy way to launch pin: edit the following makefile, set appropriate
PIN_DIR
PILP5_DIR
and run make.Ex1 makefile
:############################################################################### # SECTION 1: EX1 COMPILATION ############################################################################### CC = gcc CFLAGS = -Wall -std=c99 -O3 -fno-inline -mfpmath=sse -msse2 BIN_DIR = bin SRC_DIR = src OBJ_DIR = obj SOURCE_NAMES = ex1.c OBJECT_NAMES = $(patsubst %.c,%.o,$(SOURCE_NAMES)) SOURCES = $(patsubst %,$(SRC_DIR)/%,$(SOURCE_NAMES)) OBJECTS = $(patsubst %,$(OBJ_DIR)/%,$(OBJECT_NAMES)) BINARY_NAME = ex1 BINARY = $(patsubst %,$(BIN_DIR)/%,$(BINARY_NAME)) all: $(BINARY) $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(CC) $(CFLAGS) -c $< -o $@ $(BINARY): $(OBJECTS) $(CC) $(CFLAGS) -o $(BINARY) $(OBJECTS) clean: rm -f $(BINARY) rm -f $(OBJECTS) ############################################################################### # SECTION 2: PIN/PILP5 CONFIGURATION and EXECUTION ############################################################################### PIN_DIR = /home/dparello/tutorial/pin/pin-2.12-54730-gcc.4.4.7-linux/ PILP5_DIR = /home/dparello/tutorial/Pilp5/ launchpin: $(PIN_DIR)/pin -t $(PILP5_DIR)/ilpnowrip -- ./$(BIN_DIR)/$(BINARY_NAME) ./data/1000.dat
- Result outputs are respectively a text version and a xml version of the profile
into the
perpi
directory:_ilptool.profile
and_ilptool_profile.xml
Setp 2: Getting Histogram
- Edit previous
_ilptool_command.xml
file:- Replace command tag
profile
byhistrogram
- Replace lenght tag
0
by the number of cycles +1 of Global ILP from profile output
- Replace command tag
- Run make
- Result output is a set of histogram files into
perpi
directory with the following naming convention:"function_name"_trace_depth_"d"_cid_"call_id"_ilptool.trace
- Histograms have the following structure:
Histogram structure
:Cycles BINARY COND_BR DATAXFER MISC SSE WIDENOP 0 0 0 0 0 0 0 1 2 0 1 1 0 0 2 1 1 0 1 1 1 3 2 0 0 0 1 0 4 2 1 0 0 1 0 5 2 1 0 0 1 0 6 2 1 0 0 1 0 7 2 1 0 0 1 0 8 2 1 0 0 1 0 9 2 1 0 0 1 0 10 2 1 0 0 1 0 11 2 1 0 0 1 0 12 2 1 0 0 1 0 13 2 1 0 0 1 0 14 2 1 0 0 1 0 15 2 1 0 0 1 0 16 2 1 0 0 1 0 17 2 1 0 0 1 0 18 2 1 0 0 1 0 19 2 1 0 0 1 0 20 2 1 0 0 1 0
c
for each xed_category.
Setp 3: Getting Trace
- Edit previous
_ilptool_command.xml
file:- Replace command tag
histogram
bytrace
- Replace lenght tag
0
by the number of instructions +1 of Global ILP from profile output
- Replace command tag
- Run make
- Result output is a set of trace files into
perpi
directory with the following naming convention:"function_name"_trace_depth_"d"_cid_"call_id"_ilptool.trace
- Traces have the following structure:
Trace structure
:0 0 0 0 INVALID 0 INVALID 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 4009c0 7 BINARY 51 CMP 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 4009c3 16 DATAXFER 15e MOVSD_XMM 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 4009c7 14 COND_BR 106 JBE 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 1 4009c9 7 BINARY 27c SUB 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 1 4009cc 26 MISC 11d LEA 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 2 4009d0 26 MISC 11d LEA 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 2 4009d5 50 WIDENOP 174 NOP 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 2 4009d8 41 SSE a ADDSD 2 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 2 4009dc 7 BINARY 7 ADD 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 3 4009e0 7 BINARY 51 CMP 9 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0
- Column 1 indicates the dynamic instruction number.
- Column 2 indicates the execution cycle number.
- Column 3 indicates assembly address of the instruction.
- Column 4 indicates its xed_category number.
- Column 5 indicates its xed_category name.
- Column 6 indicates its op_code number.
- Column 7 indicates its op_code name.
- Column 8 to 18 indicates source dependencies (each number is the dynamic instruction number of the producer).
Source organisation
Each function call has its own analysis. Thus Independantly of which analysis is provide (profiling, histogram or trace), the analyser class is coupled with a routine class which control when analysis start and stop.Instrumentation
main
function callRoutineLoad
which foreach routinertn
callInstructionRoutine
function to instrument it.
Profile analysis
Histogram analysis
Trace analysis
Full code
Pilp5
- Main, interfaces and instrumentation
Pilp5/main.cpp
:/*BEGIN_LEGAL Intel Open Source License Copyright (c) 2002-2009 Intel Corporation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. END_LEGAL */ #include <locale> #include <iostream> #include <fstream> #include <string> #include "pin.H" #include "tools/ilpprofile.hh" #include "tools/ilphistogram.hh" #include "tools/ilptrace.hh" #include "instrument.hh" #include "options.hh" #include <unistd.h> using std::cout; using std::cerr; using std::endl; using std::ofstream; using std::ifstream; using std::string; IlptoolInterface *main_ilp;//("GLOBAL"); string MainImageName = ""; vector<IlptoolInterface *> IlpList; ofstream outfile; ofstream outxml; VOID RoutineLoad(IMG img, VOID *v) { cerr << "Loading image: " << IMG_Name(img) << endl; if (IMG_IsMainExecutable(img)) MainImageName = IMG_Name(img).c_str(); cerr << "\tMain image: " << IMG_Name(img) << endl; // Forward pass over all sections in an image for( SEC sec= IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec) ) { if (SEC_IsExecutable(sec)) { // Forward pass over all routines in a section for( RTN rtn= SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn) ) { // Register Routine to be called to instrument rtn InstrumentRoutine(rtn, v); } } } } Options options; // argc, argv are the entire command line, including pin -t <toolname> -- ... int main(int argc, char * argv[]) { options.ReadXML(); string profile_filename = options.option_list["resdir"] + ("/_ilptool.profile"); cerr << "OUTFILE: " << profile_filename << endl; outfile.open(profile_filename.c_str()); if (options.option_list["command"]=="profile") { main_ilp = new IlpProfile("GLOBAL", 0, 0); string profile_xmlfilename = options.option_list["resdir"] + ("/_ilptool_profile.xml"); cerr << "OUTXML: " << profile_xmlfilename << endl; outxml.open(profile_xmlfilename.c_str()); outxml << "<?xml version=\"1.0\"?>" << endl << endl; outxml << "<profile>" << endl; } if(options.option_list["command"]=="histogram") { main_ilp = new IlpHistogram("GLOBAL", 0, 0); string profile_xmlfilename = options.option_list["resdir"] + ("/_ilptool_profile_dummy_h.xml"); cerr << "OUTXML: " << profile_xmlfilename << endl; outxml.open(profile_xmlfilename.c_str()); outxml << "<?xml version=\"1.0\"?>" << endl << endl; outxml << "<profile>" << endl; } if(options.option_list["command"]=="trace") { main_ilp = new IlpTrace("GLOBAL", 0, 0); string profile_xmlfilename = options.option_list["resdir"] + ("/_ilptool_profile_dummy_t.xml"); cerr << "OUTXML: " << profile_xmlfilename << endl; outxml.open(profile_xmlfilename.c_str()); outxml << "<?xml version=\"1.0\"?>" << endl << endl; outxml << "<profile>" << endl; } #if defined(TARGET_IA32E) cerr << "\tTARGET_IA32E (Registers for TARGET_IA32 with Extension)" << endl; #else cerr << "\tTARGET_IA32 (Registers for TARGET_IA32 without Extension)" << endl; #endif // if (!options.ht_all) if (options.option_list["inst_control"]!="all") main_ilp->stop(); IlpList.push_back(main_ilp); // Initialize symbol table code, needed for rtn instrumentation PIN_InitSymbols(); // Initialize pin PIN_Init(argc, argv); // Register ImageLoad to be called when an image is loaded IMG_AddInstrumentFunction(RoutineLoad, 0); // Register Fini to be called when the application exits PIN_AddFiniFunction(InstrumentFini, 0); // Start the program, never returns PIN_StartProgram(); return 0; }
Pilp5/instrument.hh
:#ifndef INSTRUMENT_HH #define INSTRUMENT_HH #include "pin.H" #include "ilptool_interface.hh" const char * StripPath(const char * path); // INSTRUMENTATION FUNCTION VOID InstrumentAnalyse(IlptoolInterface *ilpobj, ADDRINT a, BOOL is_control, UINT32 op, UINT32 nr, UINT32 nw, UINT32 rr0, UINT32 lenrr0, UINT32 rr1, UINT32 lenrr1, UINT32 rr2, UINT32 lenrr2, UINT32 rr3, UINT32 lenrr3, UINT32 rr4, UINT32 lenrr4, UINT32 rr5, UINT32 lenrr5, UINT32 rr6, UINT32 lenrr6, UINT32 rr7, UINT32 lenrr7, UINT32 wr0, UINT32 lenwr0, UINT32 wr1, UINT32 lenwr1, UINT32 wr2, UINT32 lenwr2, UINT32 wr3, UINT32 lenwr3, UINT32 wr4, UINT32 lenwr4, UINT32 wr5, UINT32 lenwr5, UINT32 wr6, UINT32 lenwr6, UINT32 wr7, UINT32 lenwr7, ADDRINT amr, UINT32 rsize, ADDRINT amr2, ADDRINT amw, UINT32 wsize, UINT32 xed_category); // Pin calls this function every time a new rtn is executed VOID InstrumentRoutine(RTN rtn, VOID *v); // This function is called when the application exits // It prints the name and count for each procedure VOID InstrumentFini(INT32 code, VOID *v); #endif // INSTRUMENT_HH
Pilp5/instrument.cpp
:#include "instrument.hh" #include "tools/ilpprofile.hh" #include "tools/ilphistogram.hh" #include "tools/ilptrace.hh" #include "extern.hh" #include "sstream" const char * StripPath(const char * path) { const char * file = strrchr(path,'/'); if (file) return file+1; else return path; } // INSTRUMENTATION FUNCTION VOID InstrumentAnalyse(IlptoolInterface *ilpobj, ADDRINT a, BOOL is_control, UINT32 op, UINT32 nr, UINT32 nw, UINT32 rr0, UINT32 lenrr0, UINT32 rr1, UINT32 lenrr1, UINT32 rr2, UINT32 lenrr2, UINT32 rr3, UINT32 lenrr3, UINT32 rr4, UINT32 lenrr4, UINT32 rr5, UINT32 lenrr5, UINT32 rr6, UINT32 lenrr6, UINT32 rr7, UINT32 lenrr7, UINT32 wr0, UINT32 lenwr0, UINT32 wr1, UINT32 lenwr1, UINT32 wr2, UINT32 lenwr2, UINT32 wr3, UINT32 lenwr3, UINT32 wr4, UINT32 lenwr4, UINT32 wr5, UINT32 lenwr5, UINT32 wr6, UINT32 lenwr6, UINT32 wr7, UINT32 lenwr7, ADDRINT amr, UINT32 rsize, ADDRINT amr2, ADDRINT amw, UINT32 wsize, UINT32 xed_category) { if (ilpobj) { Register rr[8]; Register wr[8]; rr[0].num = rr0; rr[1].num = rr1; rr[2].num = rr2; rr[3].num = rr3; rr[4].num = rr4; rr[5].num = rr5; rr[6].num = rr6; rr[7].num = rr7; rr[0].len = lenrr0; rr[1].len = lenrr1; rr[2].len = lenrr2; rr[3].len = lenrr3; rr[4].len = lenrr4; rr[5].len = lenrr5; rr[6].len = lenrr6; rr[7].len = lenrr7; wr[0].num = wr0; wr[1].num = wr1; wr[2].num = wr2; wr[3].num = wr3; wr[4].num = wr4; wr[5].num = wr5; wr[6].num = wr6; wr[7].num = wr7; wr[0].len = lenwr0; wr[1].len = lenwr1; wr[2].len = lenwr2; wr[3].len = lenwr3; wr[4].len = lenwr4; wr[5].len = lenwr5; wr[6].len = lenwr6; wr[7].len = lenwr7; Instruction instr(a, (bool)is_control, op, nr, nw, rr, wr, amr, rsize, amr2, amw, wsize, (xed_category_enum_t)xed_category ); ilpobj->analyse(instr); } } // ILP COMPUTATION VOID startacall(RoutineInterface *rtn) { rtn->start(); } VOID stopacall(RoutineInterface *rtn) { rtn->stop(); } // Pin calls this function every time a new rtn is executed VOID InstrumentRoutine(RTN rtn, VOID *v) { RoutineInterface *ri; if (options.option_list["command"]=="profile") { ri = new RoutineProfile(RTN_Name(rtn).c_str(), //StripPath(IMG_Name(SEC_Img(RTN_Sec(rtn))).c_str()), IMG_Name(SEC_Img(RTN_Sec(rtn))).c_str(), RTN_Address(rtn), rtn, main_ilp); } else if (options.option_list["command"]=="histogram") { ri = new RoutineHistogram(RTN_Name(rtn).c_str(), //StripPath(IMG_Name(SEC_Img(RTN_Sec(rtn))).c_str()), IMG_Name(SEC_Img(RTN_Sec(rtn))).c_str(), RTN_Address(rtn), rtn, main_ilp); } else if (options.option_list["command"]=="trace") { ri = new RoutineTrace(RTN_Name(rtn).c_str(), //StripPath(IMG_Name(SEC_Img(RTN_Sec(rtn))).c_str()), IMG_Name(SEC_Img(RTN_Sec(rtn))).c_str(), RTN_Address(rtn), rtn, main_ilp); } else { cerr << "Bad option !!!" << endl; abort(); } RTN_Open(rtn); RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)startacall, IARG_PTR, ri, IARG_END); RTN_InsertCall(rtn, IPOINT_AFTER, (AFUNPTR)stopacall, IARG_PTR, ri, IARG_END); for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)) { // IlpList[0]->InstrumentInstructionTrace(ins, 0); IlpList[0]->instrument(ins, 0); } RTN_Close(rtn); } // This function is called when the application exits // It prints the name and count for each procedure VOID InstrumentFini(INT32 code, VOID *v) { // Output on xml file outxml << endl; // if(options.ht_all) if(options.option_list["inst_control"]=="all") { outfile << endl; outfile << "Global ILP "; IlpList[0]->dump(outfile); outfile << endl; // We need to close the _start call function which never return outxml << "</call>" << endl; outxml << "<global>"<< endl; IlpList[0]->dumpxml(outxml, 0); outxml << "</global>"<< endl; } outxml << "</profile>"<<endl; outxml << endl; }
Pilp5/ilptool_interface.hh
:#ifndef ILPTOOL_INTERFACE_HH #define ILPTOOL_INTERFACE_HH #include "ilpcommon.hh" class IlptoolInterface { public: IlptoolInterface(const char *nickname, uint32_t depth, uint32_t call_id); virtual void instrument(INS ins, VOID *v)=0; virtual void analyse(Instruction &instr)=0; virtual void dump(ostream & os)=0; virtual void dumpxml(ostream & os, int depth)=0; virtual void stop()=0; virtual ~IlptoolInterface(); IlptoolInterface *next_ilp; string name; uint32_t call_depth; uint32_t call_id; }; class RoutineInterface { public: RoutineInterface(const char *name, const char *image, ADDRINT addr, RTN rtn, UINT64 rncnt, UINT64 dephcnt, UINT64 startdepth, IlptoolInterface *ilp); virtual void start()=0; virtual void stop()=0; virtual ~RoutineInterface(); // Control functions bool ctrl_start(); bool ctrl_stop(); uint32_t get_depth(); protected: // ROUTINE INFORMATION string rtn_name; string rtn_image; ADDRINT rtn_address; RTN rtn_rtn; UINT64 rtn_rtnCount; UINT64 rtn_depth_counter; UINT64 rtn_start_depth; bool is_rtn_starting_instrumentation; // STATIC (global) INFORMATION public: uint32_t local_cid; static uint32_t call_depth; static uint32_t call_id; static bool is_instrument_on; }; #endif // ILPTOOL_INTERFACE_HH
Pilp5/ilptool_interface.cpp
:#include "ilptool_interface.hh" #include "extern.hh" IlptoolInterface::IlptoolInterface(const char *nickname, uint32_t dh, uint32_t cid): name(nickname), call_depth(dh), call_id(cid){} IlptoolInterface::~IlptoolInterface() {} RoutineInterface::RoutineInterface(const char *name, const char *image, ADDRINT addr, RTN rtn, UINT64 rncnt, UINT64 dephcnt, UINT64 startdepth, IlptoolInterface *ilp): rtn_name(name), rtn_image(image), rtn_address(addr), rtn_rtn(rtn), rtn_rtnCount(0), rtn_depth_counter(0), rtn_start_depth(0), is_rtn_starting_instrumentation(false) {} RoutineInterface::~RoutineInterface() {} bool RoutineInterface::ctrl_start() { // We ignore ".plt" functions... if (this->rtn_name.compare(".plt") != 0) { call_id++; local_cid = call_id; if ( (// IF user want to dump all functions (options.option_list["dump_control"]=="all") || // OR user want to dump main image functions ( (options.option_list["dump_control"]=="main") && (rtn_image == MainImageName) ) ) && // AND user depth is greater than current depth ( ( (uint32_t)atoi(options.option_list["depth"].c_str()) > call_depth-rtn_start_depth ) ) ) { //call_id++; rtn_depth_counter++; call_depth++; return true; } } return false; } bool RoutineInterface::ctrl_stop() { bool ret = ( (// IF user want to dump all functions (options.option_list["dump_control"]=="all") || // OR user want to dump main image functions ( (options.option_list["dump_control"]=="main") && (rtn_image == MainImageName) ) ) &&//|| is_instrument_on) && ( ((uint32_t)atoi(options.option_list["depth"].c_str()) > call_depth-rtn_start_depth) ) ); if (ret) { call_depth--; rtn_depth_counter--; if (is_rtn_starting_instrumentation && (rtn_depth_counter <= 0) ) { is_instrument_on = false; } } return ret; } uint32_t RoutineInterface::get_depth() { return call_depth; } uint32_t RoutineInterface::call_depth = 0; uint32_t RoutineInterface::call_id = 0; bool RoutineInterface::is_instrument_on = false;
Profile analysis
Pilp5/tools/ilpprofile.hh
:
#ifndef ILPPROFILE_HH #define ILPPROFILE_HH #include "pin.H" #include "ilptool_interface.hh" #include "ilpcommon.hh" #include "utils/memory.hh" #include "utils/memory.tcc" extern "C" { #include "xed-category-enum.h" } class IlpProfile: public IlptoolInterface{ protected: Memory<unsigned long> memory; // Memory<unsigned long> memory_trace; uint32_t rat[REG_FILE_SIZE], nbread[REG_FILE_SIZE], nbwrite[REG_FILE_SIZE], npg; // unsigned long rat_trace[REG_FILE_SIZE];//, nbread[REG_FILE_SIZE], nbwrite[REG_FILE_SIZE], npg; public: bool is_main; // string name; public: uint32_t nbcycles; uint32_t numinst; public: IlpProfile(const char *nickname, uint32_t dh, uint32_t cid); ~IlpProfile(); // IlptoolInterface void instrument(INS ins, VOID *v); void analyse(Instruction &instr); void dump(ostream &os); void dumpxml(ostream &os, int depth); void stop(); // VOID writetoreg(uint32_t c, UINT32 nw, // UINT32 op, // UINT32 wr0, UINT32 lenwr0, // UINT32 wr1, UINT32 lenwr1, // UINT32 wr2, UINT32 lenwr2, // UINT32 wr3, UINT32 lenwr3); // uint32_t readfromreg(UINT32 nr, // UINT32 rr0, UINT32 lenrr0, // UINT32 rr1, UINT32 lenrr1, // UINT32 rr2, UINT32 lenrr2, // UINT32 rr3, UINT32 lenrr3); uint32_t readfrommem(ADDRINT amr, UINT32 rsize); VOID writetomem(uint32_t cexe, ADDRINT amw, UINT32 wsize); bool stoped; }; // END of CLASS: IlpProfile // CLASS ROUTINE PROFILE IMPLEMENTS ROUTINE INTERFACE class RoutineProfile: public RoutineInterface{ public: RoutineProfile(const char *name, const char *image, ADDRINT addr, RTN rtn, IlptoolInterface *ilp); ~RoutineProfile(); // RoutineInterface virtual void start(); virtual void stop(); }; #endif
Pilp5/tools/ilpprofile.cpp
:
extern "C" { #include "xed-interface.h" #include "xed-immdis.h" #include "xed-portability.h" } #include "pin.H" #include "tools/ilpprofile.hh" #include "instrument.hh" #include <iostream> #include <sstream> #include <iomanip> #include "options.hh" #include "extern.hh" using std::cerr; using std::endl; using std::stringstream; using std::setw; //#define DEBUG_ANALYSE 1 //////////////////////////////////////////////////////////////// // CLASS ILPPROFILE //////////////////////////////////////////////////////////////// IlpProfile::IlpProfile(const char *nickname, uint32_t dh, uint32_t cid): IlptoolInterface(nickname, dh, cid)//: histo() { unsigned long i; for (i=0;i<REG_FILE_SIZE;i++){ rat[i]=0; nbread[i]=0; nbwrite[i]=0; } nbcycles=0; npg=0; numinst=0; memory.Reset(); // memory_trace.Reset(); stoped = false; is_main = false; //name = nickname; } IlpProfile::~IlpProfile() {} /////////////////////////////////////////////////////////// ////////// START OF /// ILP COMPUTE FUNCTIONS ///////////// /////////////////////////////////////////////////////////// //VOID IlpProfile::global_compute(Instruction &instr)//, VOID IlpProfile::analyse(Instruction &instr) { uint32_t c,c1,c2,c3,cexe; c = 0; if(!stoped) { numinst++; #ifdef DEBUG_ANALYSE if (instr.nbr>Instruction::MAXRRDEP) { cerr << "ERROR instruction have too many sources !!!" << endl; // cerr << instr << endl; instr.dump(cerr); cerr << endl; abort(); } #endif // Read cycle from registers c1=0; for (unsigned int i=0;i<instr.nbr;i++){ for (unsigned int j=0;j<instr.rr[i].len;j++){ c1=((c=rat[instr.rr[i].num+j])>c1)?c:c1; } } // cexe=c1; c2=(instr.amr)?readfrommem(instr.amr, instr.rsize):0; c3=(instr.amr2)?readfrommem(instr.amr2, instr.rsize):0; cexe=(c1>c2)?c1:c2; cexe=(c3>cexe)?c3:cexe; cexe++; // Write to registers #ifdef DEBUG_ANALYSE if (instr.nbw>Instruction::MAXWRDEP) { cerr << "ERROR instruction have too many destinations !!!" << endl; // cerr << instr << endl; instr.dump(cerr); cerr << endl; abort(); } #endif const char *opcode; char oponstack, opcontrol; opcode = OPCODE_StringShort(instr.opcode).c_str(); oponstack = !(strcmp(opcode,"PUSH") && strcmp(opcode,"POP") && strcmp(opcode,"CALL_NEAR") && strcmp(opcode,"RET_NEAR")); opcontrol = (opcode[0]=='J') || !strcmp(opcode,"CALL_NEAR") || !strcmp(opcode,"RET_NEAR") || !strcmp(opcode,"SYSCALL"); for (unsigned int i=0;i<instr.nbw;i++){ #if defined(TARGET_IA32E) // if (oponstack && (instr.wr[i].num==REG_RSP)) continue; // if (opcontrol && (instr.wr[i].num==REG_RIP)) continue; if (oponstack && (instr.wr[i].num==RSP)) continue; if (opcontrol && (instr.wr[i].num==RIP)) continue; #else if (oponstack && (instr.wr[i].num==ESP)) continue; if (opcontrol && (instr.wr[i].num==RIP)) continue; #endif for (unsigned int j=0;j<instr.wr[i].len;j++){ rat[instr.wr[i].num+j]=cexe; // nbwrite[instr.wr[i].num+j]++; } } if(instr.amw) writetomem(cexe, instr.amw, instr.wsize); nbcycles=(cexe>nbcycles)?cexe:nbcycles; } if (next_ilp) next_ilp->analyse(instr); } /////////////////////////////////////////////////////////// ////////// END OF /// ILP COMPUTE FUNCTIONS /////////////// /////////////////////////////////////////////////////////// // Pin calls this function every time a new instruction is encountered VOID IlpProfile::instrument(INS ins, VOID *v) { UINT32 nr, nw, i; OPCODE op; // struct {UINT32 num; UINT32 len;} rr[8], wr[8]; Register rr[8], wr[8]; // ADDRINT a; // a = INS_Address(ins); // Instruction *localinstr; IlpProfile *this_or_next = this; bool is_float=false; /* if ( INS_RepPrefix(ins) || INS_RepnePrefix(ins) ) { // WARNING DO NOT USE REP Prefixed INSTRUCTION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! xed_decoded_inst_t* xedd = INS_XedDec(ins); // xed_operand_values_t* xedv = INS_xed_operand_values(ins); xed_operand_values_t* xedv = xed_decoded_inst_operands(xedd); bool real_rep = xed_operand_values_has_real_rep(xedv); if (real_rep) { // you have a 'real' rep prefix cerr << "REP prefix detected and not supported yet !!!" << endl; cerr << "Instruction address: " << hex << a << dec << endl; cerr << INS_Disassemble(ins).c_str() << endl; abort(); } } */ op = INS_Opcode(ins); nr = INS_MaxNumRRegs(ins); if(nr>8) { cerr << "NR > 8 !!!" <<endl; abort(); } for (i=0; i<nr; i++){ rr[i].num = reg2int(INS_RegR(ins, i), &rr[i].len); if (REG_is_fr(INS_RegR(ins, i))) is_float=true; if (rr[i].num > 10000) { cerr << "RR > 10000 !!!" <<endl; cerr << hex << INS_Address(ins) << dec << "\t" << INS_Mnemonic(ins) << endl; cerr << hex << INS_Address(ins) << dec << "\t" << INS_Disassemble(ins) << endl; abort(); } } nw = INS_MaxNumWRegs(ins); if(nw>8) { cerr << "NW > 8 !!!" <<endl; abort(); } for (i=0; i<nw; i++){ wr[i].num = reg2int(INS_RegW(ins, i), &wr[i].len); if (REG_is_fr(INS_RegW(ins, i))) is_float=true; if (wr[i].num > 10000) { cerr << "WR > 10000 !!!: " << wr[i].num << endl; cerr << hex << INS_Address(ins) << dec << "\t" << INS_Mnemonic(ins) << endl; cerr << hex << INS_Address(ins) << dec << "\t" << INS_Disassemble(ins) << endl; abort(); } } bool is_control; if (INS_IsBranchOrCall(ins)) is_control=true; else is_control=false; UINT32 xed_category = INS_Category(ins); if ((options.option_list["floatonly"]=="0") || is_float) { if (INS_IsMemoryRead(ins) && INS_HasMemoryRead2(ins) && INS_IsMemoryWrite(ins)){ INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(InstrumentAnalyse), IARG_PTR, this_or_next, IARG_INST_PTR, IARG_BOOL, (BOOL)is_control, IARG_UINT32, (UINT32)op, IARG_UINT32, nr, IARG_UINT32, nw, IARG_UINT32, rr[0].num, IARG_UINT32, rr[0].len, IARG_UINT32, rr[1].num, IARG_UINT32, rr[1].len, IARG_UINT32, rr[2].num, IARG_UINT32, rr[2].len, IARG_UINT32, rr[3].num, IARG_UINT32, rr[3].len, IARG_UINT32, rr[4].num, IARG_UINT32, rr[4].len, IARG_UINT32, rr[5].num, IARG_UINT32, rr[5].len, IARG_UINT32, rr[6].num, IARG_UINT32, rr[6].len, IARG_UINT32, rr[7].num, IARG_UINT32, rr[7].len, IARG_UINT32, wr[0].num, IARG_UINT32, wr[0].len, IARG_UINT32, wr[1].num, IARG_UINT32, wr[1].len, IARG_UINT32, wr[2].num, IARG_UINT32, wr[2].len, IARG_UINT32, wr[3].num, IARG_UINT32, wr[3].len, IARG_UINT32, wr[4].num, IARG_UINT32, wr[4].len, IARG_UINT32, wr[5].num, IARG_UINT32, wr[5].len, IARG_UINT32, wr[6].num, IARG_UINT32, wr[6].len, IARG_UINT32, wr[7].num, IARG_UINT32, wr[7].len, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_MEMORYREAD2_EA, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_UINT32, xed_category, IARG_END); } else if (INS_IsMemoryRead(ins) && INS_HasMemoryRead2(ins)){ INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(InstrumentAnalyse), IARG_PTR, this_or_next, IARG_INST_PTR, IARG_BOOL, (BOOL)is_control, IARG_UINT32, (UINT32)op, IARG_UINT32, nr, IARG_UINT32, nw, IARG_UINT32, rr[0].num, IARG_UINT32, rr[0].len, IARG_UINT32, rr[1].num, IARG_UINT32, rr[1].len, IARG_UINT32, rr[2].num, IARG_UINT32, rr[2].len, IARG_UINT32, rr[3].num, IARG_UINT32, rr[3].len, IARG_UINT32, rr[4].num, IARG_UINT32, rr[4].len, IARG_UINT32, rr[5].num, IARG_UINT32, rr[5].len, IARG_UINT32, rr[6].num, IARG_UINT32, rr[6].len, IARG_UINT32, rr[7].num, IARG_UINT32, rr[7].len, IARG_UINT32, wr[0].num, IARG_UINT32, wr[0].len, IARG_UINT32, wr[1].num, IARG_UINT32, wr[1].len, IARG_UINT32, wr[2].num, IARG_UINT32, wr[2].len, IARG_UINT32, wr[3].num, IARG_UINT32, wr[3].len, IARG_UINT32, wr[4].num, IARG_UINT32, wr[4].len, IARG_UINT32, wr[5].num, IARG_UINT32, wr[5].len, IARG_UINT32, wr[6].num, IARG_UINT32, wr[6].len, IARG_UINT32, wr[7].num, IARG_UINT32, wr[7].len, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_MEMORYREAD2_EA, IARG_ADDRINT, 0L, IARG_UINT32, 0, IARG_UINT32, xed_category, IARG_END); } else if (INS_IsMemoryRead(ins) && INS_IsMemoryWrite(ins)){ INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(InstrumentAnalyse), IARG_PTR, this_or_next, IARG_INST_PTR, IARG_BOOL, (BOOL)is_control, IARG_UINT32, (UINT32)op, IARG_UINT32, nr, IARG_UINT32, nw, IARG_UINT32, rr[0].num, IARG_UINT32, rr[0].len, IARG_UINT32, rr[1].num, IARG_UINT32, rr[1].len, IARG_UINT32, rr[2].num, IARG_UINT32, rr[2].len, IARG_UINT32, rr[3].num, IARG_UINT32, rr[3].len, IARG_UINT32, rr[4].num, IARG_UINT32, rr[4].len, IARG_UINT32, rr[5].num, IARG_UINT32, rr[5].len, IARG_UINT32, rr[6].num, IARG_UINT32, rr[6].len, IARG_UINT32, rr[7].num, IARG_UINT32, rr[7].len, IARG_UINT32, wr[0].num, IARG_UINT32, wr[0].len, IARG_UINT32, wr[1].num, IARG_UINT32, wr[1].len, IARG_UINT32, wr[2].num, IARG_UINT32, wr[2].len, IARG_UINT32, wr[3].num, IARG_UINT32, wr[3].len, IARG_UINT32, wr[4].num, IARG_UINT32, wr[4].len, IARG_UINT32, wr[5].num, IARG_UINT32, wr[5].len, IARG_UINT32, wr[6].num, IARG_UINT32, wr[6].len, IARG_UINT32, wr[7].num, IARG_UINT32, wr[7].len, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_ADDRINT, 0L, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_UINT32, xed_category, IARG_END); } else if (INS_IsMemoryRead(ins)){ INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(InstrumentAnalyse), IARG_PTR, this_or_next, IARG_INST_PTR, IARG_BOOL, (BOOL)is_control, IARG_UINT32, (UINT32)op, IARG_UINT32, nr, IARG_UINT32, nw, IARG_UINT32, rr[0].num, IARG_UINT32, rr[0].len, IARG_UINT32, rr[1].num, IARG_UINT32, rr[1].len, IARG_UINT32, rr[2].num, IARG_UINT32, rr[2].len, IARG_UINT32, rr[3].num, IARG_UINT32, rr[3].len, IARG_UINT32, rr[4].num, IARG_UINT32, rr[4].len, IARG_UINT32, rr[5].num, IARG_UINT32, rr[5].len, IARG_UINT32, rr[6].num, IARG_UINT32, rr[6].len, IARG_UINT32, rr[7].num, IARG_UINT32, rr[7].len, IARG_UINT32, wr[0].num, IARG_UINT32, wr[0].len, IARG_UINT32, wr[1].num, IARG_UINT32, wr[1].len, IARG_UINT32, wr[2].num, IARG_UINT32, wr[2].len, IARG_UINT32, wr[3].num, IARG_UINT32, wr[3].len, IARG_UINT32, wr[4].num, IARG_UINT32, wr[4].len, IARG_UINT32, wr[5].num, IARG_UINT32, wr[5].len, IARG_UINT32, wr[6].num, IARG_UINT32, wr[6].len, IARG_UINT32, wr[7].num, IARG_UINT32, wr[7].len, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_ADDRINT, 0L, IARG_ADDRINT, 0L, IARG_UINT32, 0, IARG_UINT32, xed_category, IARG_END); } else if (INS_IsMemoryWrite(ins)){ INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(InstrumentAnalyse), IARG_PTR, this_or_next, IARG_INST_PTR, IARG_BOOL, (BOOL)is_control, IARG_UINT32, (UINT32)op, IARG_UINT32, nr, IARG_UINT32, nw, IARG_UINT32, rr[0].num, IARG_UINT32, rr[0].len, IARG_UINT32, rr[1].num, IARG_UINT32, rr[1].len, IARG_UINT32, rr[2].num, IARG_UINT32, rr[2].len, IARG_UINT32, rr[3].num, IARG_UINT32, rr[3].len, IARG_UINT32, rr[4].num, IARG_UINT32, rr[4].len, IARG_UINT32, rr[5].num, IARG_UINT32, rr[5].len, IARG_UINT32, rr[6].num, IARG_UINT32, rr[6].len, IARG_UINT32, rr[7].num, IARG_UINT32, rr[7].len, IARG_UINT32, wr[0].num, IARG_UINT32, wr[0].len, IARG_UINT32, wr[1].num, IARG_UINT32, wr[1].len, IARG_UINT32, wr[2].num, IARG_UINT32, wr[2].len, IARG_UINT32, wr[3].num, IARG_UINT32, wr[3].len, IARG_UINT32, wr[4].num, IARG_UINT32, wr[4].len, IARG_UINT32, wr[5].num, IARG_UINT32, wr[5].len, IARG_UINT32, wr[6].num, IARG_UINT32, wr[6].len, IARG_UINT32, wr[7].num, IARG_UINT32, wr[7].len, IARG_ADDRINT, 0L, IARG_UINT32, 0, IARG_ADDRINT, 0L, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_UINT32, xed_category, IARG_END); } else{ INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(InstrumentAnalyse), IARG_PTR, this_or_next, IARG_INST_PTR, IARG_BOOL, (BOOL)is_control, IARG_UINT32, (UINT32)op, IARG_UINT32, nr, IARG_UINT32, nw, IARG_UINT32, rr[0].num, IARG_UINT32, rr[0].len, IARG_UINT32, rr[1].num, IARG_UINT32, rr[1].len, IARG_UINT32, rr[2].num, IARG_UINT32, rr[2].len, IARG_UINT32, rr[3].num, IARG_UINT32, rr[3].len, IARG_UINT32, rr[4].num, IARG_UINT32, rr[4].len, IARG_UINT32, rr[5].num, IARG_UINT32, rr[5].len, IARG_UINT32, rr[6].num, IARG_UINT32, rr[6].len, IARG_UINT32, rr[7].num, IARG_UINT32, rr[7].len, IARG_UINT32, wr[0].num, IARG_UINT32, wr[0].len, IARG_UINT32, wr[1].num, IARG_UINT32, wr[1].len, IARG_UINT32, wr[2].num, IARG_UINT32, wr[2].len, IARG_UINT32, wr[3].num, IARG_UINT32, wr[3].len, IARG_UINT32, wr[4].num, IARG_UINT32, wr[4].len, IARG_UINT32, wr[5].num, IARG_UINT32, wr[5].len, IARG_UINT32, wr[6].num, IARG_UINT32, wr[6].len, IARG_UINT32, wr[7].num, IARG_UINT32, wr[7].len, IARG_ADDRINT, 0L, IARG_UINT32, 0, IARG_ADDRINT, 0L, IARG_ADDRINT, 0L, IARG_UINT32, 0, IARG_UINT32, xed_category, IARG_END); } } } void IlpProfile::dump(ostream &os) { os << "(cid: " << call_id << ") "; os << " I[" << numinst << "]"; os << "::C[" << nbcycles << "]"; os << "::ILP[" << (double)numinst/(double)nbcycles << "]" ; } void IlpProfile::dumpxml(ostream &os, int depth) { os << setw((depth+1)*5) << ""; os << "<instructions>"<< numinst << "</instructions>"<<endl; os << setw((depth+1)*5) << ""; os << "<cycles>" << nbcycles << "</cycles>"<<endl; os << setw((depth+1)*5) << ""; os << "<ilp>" << (double)numinst/(double)nbcycles << "</ilp>"<<endl; } void IlpProfile::stop() { stoped = true; } //////////////////////////////////////////////////////////////// // END INTERFACE //////////////////////////////////////////////////////////////// uint32_t IlpProfile::readfrommem(ADDRINT amr, UINT32 rsize){ return memory.ReadMemory(amr,rsize); } VOID IlpProfile::writetomem(uint32_t cexe, ADDRINT amw, UINT32 wsize){ memory.WriteMemory(cexe, amw, wsize); } //////////////////////////////////////////////////////////////// // CLASS ROUTINEPROFILE //////////////////////////////////////////////////////////////// RoutineProfile::RoutineProfile(const char *name, const char *image, ADDRINT addr, RTN rtn, IlptoolInterface *ilp): RoutineInterface(name, image, addr, rtn, 0, 0, 0, NULL) { // if (ilp) // call_vector.push_back(ilp); } RoutineProfile::~RoutineProfile() {} void RoutineProfile::start() { if (ctrl_start()) { IlptoolInterface *new_ilp = new IlpProfile(this->rtn_name.c_str(), this->call_depth, this->call_id); (IlpList.back())->next_ilp = new_ilp; IlpList.push_back(new_ilp); // call_vector.push_back(new_ilp); outfile << setw(call_depth*5) << ""; outfile << "start : " << setw(1) << "<" /*<< rtn_image << ":"*/ << rtn_name << ">" << setw(10) << " (depth: "<< call_depth << ", lcid: "<< local_cid << ")" << endl; // XML Output outxml << setw(call_depth*5) << ""; outxml << "<call name=\""<< rtn_name //<< "\" call_id=\""<< call_id <<"\" >" << endl; outxml << setw(call_depth*5) << ""; // outxml << "<call_id>" << call_id++ << "</call_id>" << endl; //#define DEBUG_ILP_VEC 1 #ifdef DEBUG_ILP_VEC cerr << "----------DEBUG_ILP_VEC--CTRL_START--Start- " << rtn_image << "|" << rtn_name <<" ---- depth: "<< call_depth << "--- rtn_s_d: "<< rtn_start_depth << endl; for (unsigned int i=0; i<IlpList.size(); i++) cerr << " IlpList[" << i << "] = "<< IlpList[i] << " (" << IlpList[i]->name << ")" << endl; cerr << endl; cerr << "----------DEBUG_ILP_VEC--CTRL_START--Stop------------" << endl; #endif } } void RoutineProfile::stop() { IlpProfile *tmpilp=0; if (ctrl_stop()) { // FIND FUNCTION which is STOP into IlpList vector. unsigned int i; unsigned int count=0; for (i=IlpList.size()-1; i>0; i--) { if (rtn_name == IlpList[i]->name) break; count++; } if (count == IlpList.size()-1 ) { outfile << setw((call_depth+1)*5) << ""; outfile << "imp. stop ?: " << setw(1) << "<" << rtn_name << "> (cid: " // outfile << "imp. stop ?: " << setw(1) << "<" << (IlpList.back())->name << "> (cid: " << (IlpList.back())->call_id << ") " << "> (lcid: " << local_cid << ") "; tmpilp = (IlpProfile *)(IlpList.back()); tmpilp->dump(outfile); tmpilp->dumpxml(outxml, call_depth+1); outfile << endl; call_depth++; } else if (count>0) { { // for (j=IlpList.size()-1; j>i; j--) for (unsigned int j=0; j<count; j++ ) { outfile << setw((call_depth+1)*5) << ""; outfile << "imp. stop: " << setw(1) << "<" << (IlpList.back())->name<< "> (cid: " << (IlpList.back())->call_id << ") " << "> (lcid: " << local_cid << ") "; tmpilp = (IlpProfile *)(IlpList.back()); tmpilp->dump(outfile); tmpilp->dumpxml(outxml, call_depth+1); outfile << endl; (IlpList.back())->stop(); IlpList.pop_back(); delete tmpilp; (IlpList.back())->next_ilp = NULL; } //call_depth++; } // Perform the explicite STOP outfile << setw((call_depth+1)*5) << ""; outfile << "stop : " << setw(1) << "<" << rtn_name << ">" ; outfile << " (depth: "<< (call_depth+1) << ", lcid: "<< local_cid <<")"; // XML Output outxml << setw((call_depth+2)*5) << ""; outxml << "<name>"<< rtn_name << "</name>"<<endl; outxml << setw((call_depth+2)*5) << ""; outxml << "<cid>"<< (IlpList.back())->call_id << "</cid>"<<endl; outxml << setw((call_depth+2)*5) << ""; outxml << "<depth>"<< call_depth+1 << "</depth>"<<endl; if (IlpList.size()>1) { tmpilp = (IlpProfile *)IlpList.back(); tmpilp->dump(outfile); tmpilp->dumpxml(outxml, call_depth+1); outfile << endl; } outxml << setw((call_depth+1)*5) << ""; outxml << "</call>" << endl; if(IlpList.size()>1) { (IlpList.back())->stop(); IlpList.pop_back(); delete tmpilp; if (IlpList.size()>0) (IlpList.back())->next_ilp = NULL; } } else { // if (count) outfile << setw((call_depth+1)*5) << ""; outfile << "stop : " << setw(1) << "<" << rtn_name << ">" ; outfile << " (depth: "<< (call_depth+1) << ", lcid: "<< local_cid <<")";// << " rtn_s_d: "<< rtn_start_depth << ")";// << endl; // XML Output outxml << setw((call_depth+2)*5) << ""; outxml << "<name>"<< rtn_name << "</name>"<<endl; outxml << setw((call_depth+2)*5) << ""; outxml << "<cid>"<< (IlpList.back())->call_id << "</cid>"<<endl; outxml << setw((call_depth+2)*5) << ""; outxml << "<depth>"<< call_depth+1 << "</depth>"<<endl; if (IlpList.size()>1) { tmpilp = (IlpProfile *)IlpList.back(); tmpilp->dump(outfile); tmpilp->dumpxml(outxml, call_depth+1); outfile << endl; } outxml << setw((call_depth+1)*5) << ""; outxml << "</call>" << endl; if(IlpList.size()>1) { (IlpList.back())->stop(); IlpList.pop_back(); delete tmpilp; if (IlpList.size()>0) (IlpList.back())->next_ilp = NULL; } } #ifdef DEBUG_ILP_VEC cerr << "----------DEBUG_ILP_VEC--CTRL_STOP--Start- " << rtn_image << "|" << rtn_name <<" ---- depth: "<< call_depth << "--- rtn_s_d: "<< rtn_start_depth << endl; for (unsigned int i=0; i<IlpList.size(); i++) cerr << " IlpList[" << i << "] = "<< IlpList[i] << " (" << IlpList[i]->name << ")"<< endl; cerr << endl; cerr << "----------DEBUG_ILP_VEC---CTRL_STOP-- Stop ------------" << endl; #endif } }
Histogram analysis
Pilp5/tools/ilphistogram.hh
:
#ifndef ILPHISTOGRAM_HH #define ILPHISTOGRAM_HH #include "pin.H" #include "ilptool_interface.hh" #include "ilpcommon.hh" #include "utils/memory.hh" #include "utils/memory.tcc" #include "tools/histogram.hh" extern "C" { #include "xed-category-enum.h" } class IlpHistogram: public IlptoolInterface{ protected: Memory<unsigned long> memory; uint32_t rat[REG_FILE_SIZE], nbread[REG_FILE_SIZE], nbwrite[REG_FILE_SIZE], npg; public: bool is_main; public: uint32_t nbcycles; uint32_t numinst; public: Histogram histo; public: IlpHistogram(const char *nickname, uint32_t dh, uint32_t cid); ~IlpHistogram(); // IlptoolInterface void instrument(INS ins, VOID *v); void analyse(Instruction &instr); void dump(ostream &os); void dumpxml(ostream &os, int depth); void stop(); // VOID writetoreg(uint32_t c, UINT32 nw, // UINT32 op, // UINT32 wr0, UINT32 lenwr0, // UINT32 wr1, UINT32 lenwr1, // UINT32 wr2, UINT32 lenwr2, // UINT32 wr3, UINT32 lenwr3); // uint32_t readfromreg(UINT32 nr, // UINT32 rr0, UINT32 lenrr0, // UINT32 rr1, UINT32 lenrr1, // UINT32 rr2, UINT32 lenrr2, // UINT32 rr3, UINT32 lenrr3); uint32_t readfrommem(ADDRINT amr, UINT32 rsize); VOID writetomem(uint32_t cexe, ADDRINT amw, UINT32 wsize); bool stoped; }; // END of CLASS: IlpHistogram // CLASS ROUTINE PROFILE IMPLEMENTS ROUTINE INTERFACE class RoutineHistogram: public RoutineInterface{ public: RoutineHistogram(const char *name, const char *image, ADDRINT addr, RTN rtn, IlptoolInterface *ilp); ~RoutineHistogram(); // RoutineInterface virtual void start(); virtual void stop(); // protected: // string rtn_name; // string rtn_image; // ADDRINT rtn_address; // RTN rtn_rtn; // UINT64 rtn_rtnCount; // UINT64 rtn_depth_counter; // UINT64 rtn_start_depth; // bool is_rtn_starting_instrumentation; // public: // // vector<IlptoolInterface *> call_vector; }; #endif
Pilp5/tools/ilphistogram.cpp
:
extern "C" { #include "xed-interface.h" #include "xed-immdis.h" #include "xed-portability.h" } #include "pin.H" #include "tools/ilphistogram.hh" #include "instrument.hh" #include <iostream> #include <sstream> #include <iomanip> #include "options.hh" #include "extern.hh" using std::cerr; using std::endl; using std::stringstream; //////////////////////////////////////////////////////////////// // CLASS ILPHISTOGRAM //////////////////////////////////////////////////////////////// IlpHistogram::IlpHistogram(const char *nickname, uint32_t dh, uint32_t cid):IlptoolInterface(nickname, dh, cid), histo() { unsigned long i; for (i=0;i<REG_FILE_SIZE;i++){ rat[i]=0; nbread[i]=0; nbwrite[i]=0; } nbcycles=0; npg=0; numinst=0; memory.Reset(); stoped = false; is_main = false; if(options.option_list["command"]=="histogram") { histo.resize((uint32_t)atoi(options.option_list["length"].c_str())+1); } } IlpHistogram::~IlpHistogram() {} /////////////////////////////////////////////////////////// ////////// START OF /// ILP COMPUTE FUNCTIONS ///////////// /////////////////////////////////////////////////////////// //VOID IlpHistogram::global_compute(Instruction &instr)//, VOID IlpHistogram::analyse(Instruction &instr) { uint32_t c,c1,c2,c3,cexe; if(!stoped) { numinst++; // c1=readfromreg(instr.nbr, // instr.rr[0].num, instr.rr[0].len, // instr.rr[1].num, instr.rr[1].len, // instr.rr[2].num, instr.rr[2].len, // instr.rr[3].num, instr.rr[3].len // ); // Read cycle from register // Read cycle from registers c1=0; for (unsigned int i=0;i<instr.nbr;i++){ for (unsigned int j=0;j<instr.rr[i].len;j++){ c1=((c=rat[instr.rr[i].num+j])>c1)?c:c1; } } // uint32_t IlpHistogram::readfromreg(UINT32 nr, // UINT32 rr0, UINT32 lenrr0, // UINT32 rr1, UINT32 lenrr1, // UINT32 rr2, UINT32 lenrr2, // UINT32 rr3, UINT32 lenrr3){ // uint32_t cmax, c; // unsigned int i, j, rr[4], len[4]; // rr[0]=rr0; rr[1]=rr1; rr[2]=rr2; rr[3]=rr3; // len[0]=lenrr0; len[1]=lenrr1; len[2]=lenrr2; len[3]=lenrr3; // cmax=0; // for (i=0;i<nr;i++){ // #ifdef DEBUG1 // fprintf(fd, "instruction %ld: read from reg %s\n", numinst, regx862string(rr[i], len[i])); // #endif // for (j=0;j<len[i];j++){ // cmax=((c=rat[rr[i]+j])>cmax)?c:cmax; // } // } // for (i=0;i<nr;i++){ // for (j=0;j<len[i];j++){ // nbread[rr[i]+j]++; // } // } // return cmax; // } // cexe=c1; c2=(instr.amr)?readfrommem(instr.amr, instr.rsize):0; c3=(instr.amr2)?readfrommem(instr.amr2, instr.rsize):0; cexe=(c1>c2)?c1:c2; cexe=(c3>cexe)?c3:cexe; cexe++; // Write to registers // writetoreg(cexe, instr.nbw, // instr.opcode, // instr.wr[0].num, instr.wr[0].len, // instr.wr[1].num, instr.wr[1].len, // instr.wr[2].num, instr.wr[2].len, // instr.wr[3].num, instr.wr[3].len // ); // Write to registers #ifdef DEBUG_ANALYSE if (instr.nbw>Instruction::MAXWRDEP) { cerr << "ERROR instruction have too many destinations !!!" << endl; // cerr << instr << endl; instr.dump(cerr); cerr << endl; abort(); } #endif const char *opcode; char oponstack, opcontrol; opcode = OPCODE_StringShort(instr.opcode).c_str(); oponstack = !(strcmp(opcode,"PUSH") && strcmp(opcode,"POP") && strcmp(opcode,"CALL_NEAR") && strcmp(opcode,"RET_NEAR")); opcontrol = (opcode[0]=='J') || !strcmp(opcode,"CALL_NEAR") || !strcmp(opcode,"RET_NEAR") || !strcmp(opcode,"SYSCALL"); for (unsigned int i=0;i<instr.nbw;i++){ #if defined(TARGET_IA32E) // if (oponstack && (instr.wr[i].num==REG_RSP)) continue; // if (opcontrol && (instr.wr[i].num==REG_RIP)) continue; if (oponstack && (instr.wr[i].num==RSP)) continue; if (opcontrol && (instr.wr[i].num==RIP)) continue; #else if (oponstack && (instr.wr[i].num==ESP)) continue; if (opcontrol && (instr.wr[i].num==RIP)) continue; #endif for (unsigned int j=0;j<instr.wr[i].len;j++){ rat[instr.wr[i].num+j]=cexe; // nbwrite[instr.wr[i].num+j]++; } } if(instr.amw) writetomem(cexe, instr.amw, instr.wsize); nbcycles=(cexe>nbcycles)?cexe:nbcycles; // if (options.histogram) if (options.option_list["command"]=="histogram") histo.update(cexe,instr.xed_category); } if (next_ilp) next_ilp->analyse(instr); } /////////////////////////////////////////////////////////// ////////// END OF /// ILP COMPUTE FUNCTIONS /////////////// /////////////////////////////////////////////////////////// // Pin calls this function every time a new instruction is encountered VOID IlpHistogram::instrument(INS ins, VOID *v) { UINT32 nr, nw, i; OPCODE op; Register rr[8], wr[8]; IlpHistogram *this_or_next = this; bool is_float=false; /* if ( INS_RepPrefix(ins) || INS_RepnePrefix(ins) ) { // WARNING DO NOT USE REP Prefixed INSTRUCTION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! xed_decoded_inst_t* xedd = INS_XedDec(ins); // xed_operand_values_t* xedv = INS_xed_operand_values(ins); xed_operand_values_t* xedv = xed_decoded_inst_operands(xedd); bool real_rep = xed_operand_values_has_real_rep(xedv); if (real_rep) { // you have a 'real' rep prefix cerr << "REP prefix detected and not supported yet !!!" << endl; cerr << "Instruction address: " << hex << a << dec << endl; cerr << INS_Disassemble(ins).c_str() << endl; abort(); } } */ op = INS_Opcode(ins); nr = INS_MaxNumRRegs(ins); if(nr>8) { cerr << "NR > 8 !!!" <<endl; abort(); } for (i=0; i<nr; i++){ rr[i].num = reg2int(INS_RegR(ins, i), &rr[i].len); if (REG_is_fr(INS_RegR(ins, i))) is_float=true; if (rr[i].num > 10000) { cerr << "RR > 10000 !!!" <<endl; abort(); } } nw = INS_MaxNumWRegs(ins); if(nw>8) { cerr << "NW > 8 !!!" <<endl; abort(); } for (i=0; i<nw; i++){ wr[i].num = reg2int(INS_RegW(ins, i), &wr[i].len); if (REG_is_fr(INS_RegW(ins, i))) is_float=true; if (wr[i].num > 10000) { cerr << "WR > 10000 !!!: " << wr[i].num << endl; cerr << hex << INS_Address(ins) << dec << "\t" << INS_Mnemonic(ins) << endl; cerr << hex << INS_Address(ins) << dec << "\t" << INS_Disassemble(ins) << endl; abort(); } } bool is_control; if (INS_IsBranchOrCall(ins)) is_control=true; else is_control=false; UINT32 xed_category = INS_Category(ins); if ((options.option_list["floatonly"]=="0") || is_float) { if (INS_IsMemoryRead(ins) && INS_HasMemoryRead2(ins) && INS_IsMemoryWrite(ins)) INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(InstrumentAnalyse), IARG_PTR, this_or_next, IARG_INST_PTR, IARG_BOOL, (BOOL)is_control, IARG_UINT32, (UINT32)op, IARG_UINT32, nr, IARG_UINT32, nw, IARG_UINT32, rr[0].num, IARG_UINT32, rr[0].len, IARG_UINT32, rr[1].num, IARG_UINT32, rr[1].len, IARG_UINT32, rr[2].num, IARG_UINT32, rr[2].len, IARG_UINT32, rr[3].num, IARG_UINT32, rr[3].len, IARG_UINT32, rr[4].num, IARG_UINT32, rr[4].len, IARG_UINT32, rr[5].num, IARG_UINT32, rr[5].len, IARG_UINT32, rr[6].num, IARG_UINT32, rr[6].len, IARG_UINT32, rr[7].num, IARG_UINT32, rr[7].len, IARG_UINT32, wr[0].num, IARG_UINT32, wr[0].len, IARG_UINT32, wr[1].num, IARG_UINT32, wr[1].len, IARG_UINT32, wr[2].num, IARG_UINT32, wr[2].len, IARG_UINT32, wr[3].num, IARG_UINT32, wr[3].len, IARG_UINT32, wr[4].num, IARG_UINT32, wr[4].len, IARG_UINT32, wr[5].num, IARG_UINT32, wr[5].len, IARG_UINT32, wr[6].num, IARG_UINT32, wr[6].len, IARG_UINT32, wr[7].num, IARG_UINT32, wr[7].len, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_MEMORYREAD2_EA, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_UINT32, xed_category, IARG_END); else if (INS_IsMemoryRead(ins) && INS_HasMemoryRead2(ins)) INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(InstrumentAnalyse), IARG_PTR, this_or_next, IARG_INST_PTR, IARG_BOOL, (BOOL)is_control, IARG_UINT32, (UINT32)op, IARG_UINT32, nr, IARG_UINT32, nw, IARG_UINT32, rr[0].num, IARG_UINT32, rr[0].len, IARG_UINT32, rr[1].num, IARG_UINT32, rr[1].len, IARG_UINT32, rr[2].num, IARG_UINT32, rr[2].len, IARG_UINT32, rr[3].num, IARG_UINT32, rr[3].len, IARG_UINT32, rr[4].num, IARG_UINT32, rr[4].len, IARG_UINT32, rr[5].num, IARG_UINT32, rr[5].len, IARG_UINT32, rr[6].num, IARG_UINT32, rr[6].len, IARG_UINT32, rr[7].num, IARG_UINT32, rr[7].len, IARG_UINT32, wr[0].num, IARG_UINT32, wr[0].len, IARG_UINT32, wr[1].num, IARG_UINT32, wr[1].len, IARG_UINT32, wr[2].num, IARG_UINT32, wr[2].len, IARG_UINT32, wr[3].num, IARG_UINT32, wr[3].len, IARG_UINT32, wr[4].num, IARG_UINT32, wr[4].len, IARG_UINT32, wr[5].num, IARG_UINT32, wr[5].len, IARG_UINT32, wr[6].num, IARG_UINT32, wr[6].len, IARG_UINT32, wr[7].num, IARG_UINT32, wr[7].len, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_MEMORYREAD2_EA, IARG_ADDRINT, 0L, IARG_UINT32, 0, IARG_UINT32, xed_category, IARG_END); else if (INS_IsMemoryRead(ins) && INS_IsMemoryWrite(ins)) INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(InstrumentAnalyse), IARG_PTR, this_or_next, IARG_INST_PTR, IARG_BOOL, (BOOL)is_control, IARG_UINT32, (UINT32)op, IARG_UINT32, nr, IARG_UINT32, nw, IARG_UINT32, rr[0].num, IARG_UINT32, rr[0].len, IARG_UINT32, rr[1].num, IARG_UINT32, rr[1].len, IARG_UINT32, rr[2].num, IARG_UINT32, rr[2].len, IARG_UINT32, rr[3].num, IARG_UINT32, rr[3].len, IARG_UINT32, rr[4].num, IARG_UINT32, rr[4].len, IARG_UINT32, rr[5].num, IARG_UINT32, rr[5].len, IARG_UINT32, rr[6].num, IARG_UINT32, rr[6].len, IARG_UINT32, rr[7].num, IARG_UINT32, rr[7].len, IARG_UINT32, wr[0].num, IARG_UINT32, wr[0].len, IARG_UINT32, wr[1].num, IARG_UINT32, wr[1].len, IARG_UINT32, wr[2].num, IARG_UINT32, wr[2].len, IARG_UINT32, wr[3].num, IARG_UINT32, wr[3].len, IARG_UINT32, wr[4].num, IARG_UINT32, wr[4].len, IARG_UINT32, wr[5].num, IARG_UINT32, wr[5].len, IARG_UINT32, wr[6].num, IARG_UINT32, wr[6].len, IARG_UINT32, wr[7].num, IARG_UINT32, wr[7].len, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_ADDRINT, 0L, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_UINT32, xed_category, IARG_END); else if (INS_IsMemoryRead(ins)) INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(InstrumentAnalyse), IARG_PTR, this_or_next, IARG_INST_PTR, IARG_BOOL, (BOOL)is_control, IARG_UINT32, (UINT32)op, IARG_UINT32, nr, IARG_UINT32, nw, IARG_UINT32, rr[0].num, IARG_UINT32, rr[0].len, IARG_UINT32, rr[1].num, IARG_UINT32, rr[1].len, IARG_UINT32, rr[2].num, IARG_UINT32, rr[2].len, IARG_UINT32, rr[3].num, IARG_UINT32, rr[3].len, IARG_UINT32, rr[4].num, IARG_UINT32, rr[4].len, IARG_UINT32, rr[5].num, IARG_UINT32, rr[5].len, IARG_UINT32, rr[6].num, IARG_UINT32, rr[6].len, IARG_UINT32, rr[7].num, IARG_UINT32, rr[7].len, IARG_UINT32, wr[0].num, IARG_UINT32, wr[0].len, IARG_UINT32, wr[1].num, IARG_UINT32, wr[1].len, IARG_UINT32, wr[2].num, IARG_UINT32, wr[2].len, IARG_UINT32, wr[3].num, IARG_UINT32, wr[3].len, IARG_UINT32, wr[4].num, IARG_UINT32, wr[4].len, IARG_UINT32, wr[5].num, IARG_UINT32, wr[5].len, IARG_UINT32, wr[6].num, IARG_UINT32, wr[6].len, IARG_UINT32, wr[7].num, IARG_UINT32, wr[7].len, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_ADDRINT, 0L, IARG_ADDRINT, 0L, IARG_UINT32, 0, IARG_UINT32, xed_category, IARG_END); else if (INS_IsMemoryWrite(ins)) INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(InstrumentAnalyse), IARG_PTR, this_or_next, IARG_INST_PTR, IARG_BOOL, (BOOL)is_control, IARG_UINT32, (UINT32)op, IARG_UINT32, nr, IARG_UINT32, nw, IARG_UINT32, rr[0].num, IARG_UINT32, rr[0].len, IARG_UINT32, rr[1].num, IARG_UINT32, rr[1].len, IARG_UINT32, rr[2].num, IARG_UINT32, rr[2].len, IARG_UINT32, rr[3].num, IARG_UINT32, rr[3].len, IARG_UINT32, rr[4].num, IARG_UINT32, rr[4].len, IARG_UINT32, rr[5].num, IARG_UINT32, rr[5].len, IARG_UINT32, rr[6].num, IARG_UINT32, rr[6].len, IARG_UINT32, rr[7].num, IARG_UINT32, rr[7].len, IARG_UINT32, wr[0].num, IARG_UINT32, wr[0].len, IARG_UINT32, wr[1].num, IARG_UINT32, wr[1].len, IARG_UINT32, wr[2].num, IARG_UINT32, wr[2].len, IARG_UINT32, wr[3].num, IARG_UINT32, wr[4].num, IARG_UINT32, wr[4].len, IARG_UINT32, wr[5].num, IARG_UINT32, wr[5].len, IARG_UINT32, wr[6].num, IARG_UINT32, wr[6].len, IARG_UINT32, wr[7].num, IARG_UINT32, wr[7].len, IARG_UINT32, wr[3].len, IARG_ADDRINT, 0L, IARG_UINT32, 0, IARG_ADDRINT, 0L, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_UINT32, xed_category, IARG_END); else INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(InstrumentAnalyse), IARG_PTR, this_or_next, IARG_INST_PTR, IARG_BOOL, (BOOL)is_control, IARG_UINT32, (UINT32)op, IARG_UINT32, nr, IARG_UINT32, nw, IARG_UINT32, rr[0].num, IARG_UINT32, rr[0].len, IARG_UINT32, rr[1].num, IARG_UINT32, rr[1].len, IARG_UINT32, rr[2].num, IARG_UINT32, rr[2].len, IARG_UINT32, rr[3].num, IARG_UINT32, rr[3].len, IARG_UINT32, rr[4].num, IARG_UINT32, rr[4].len, IARG_UINT32, rr[5].num, IARG_UINT32, rr[5].len, IARG_UINT32, rr[6].num, IARG_UINT32, rr[6].len, IARG_UINT32, rr[7].num, IARG_UINT32, rr[7].len, IARG_UINT32, wr[0].num, IARG_UINT32, wr[0].len, IARG_UINT32, wr[1].num, IARG_UINT32, wr[1].len, IARG_UINT32, wr[2].num, IARG_UINT32, wr[2].len, IARG_UINT32, wr[3].num, IARG_UINT32, wr[3].len, IARG_UINT32, wr[4].num, IARG_UINT32, wr[4].len, IARG_UINT32, wr[5].num, IARG_UINT32, wr[5].len, IARG_UINT32, wr[6].num, IARG_UINT32, wr[6].len, IARG_UINT32, wr[7].num, IARG_UINT32, wr[7].len, IARG_ADDRINT, 0L, IARG_UINT32, 0, IARG_ADDRINT, 0L, IARG_ADDRINT, 0L, IARG_UINT32, 0, IARG_UINT32, xed_category, IARG_END); } } void IlpHistogram::dump(ostream &os) { os << "::I[" << numinst << "]"; os << "::C[" << nbcycles << "]"; os << "::ILP[" << (double)numinst/(double)nbcycles << "]" ; // if(options.histogram) if(options.option_list["command"]=="histogram") { // static int version = 0; stringstream filename; filename << options.option_list["resdir"] << "/"; filename << IlptoolInterface::name << "_histo_depth_" << RoutineHistogram::call_depth+1 << "_cid_" << call_id << "_ilptool.histogram" ; stringstream filename2; filename2 << options.option_list["resdir"] << "/"; filename2 << IlptoolInterface::name << "_histo_depth_" << RoutineHistogram::call_depth+1 << "_cid_" << call_id << "_ilptool.histogram.colmap" ; ofstream ofile(filename.str().c_str()); ofstream ofile2(filename2.str().c_str()); histo.dump(ofile, nbcycles, ofile2); ofile.close(); ofile2.close(); #ifdef SHORT_HISTO stringstream sfilename; sfilename << options.option_list["resdir"] << "/"; sfilename << name << "_shorthisto_depth_" << RoutineHistogram::call_depth+1 << "_cid_" << call_id << "_ilptool.shorthistogram" ; ofstream sofile(sfilename.str().c_str()); histo.sdump(sofile, nbcycles); sofile.close(); #endif } } void IlpHistogram::dumpxml(ostream &os, int depth) { } void IlpHistogram::stop() { stoped = true; } //////////////////////////////////////////////////////////////// // END INTERFACE //////////////////////////////////////////////////////////////// // VOID IlpHistogram::writetoreg(uint32_t c, UINT32 nw, // UINT32 op, // UINT32 wr0, UINT32 lenwr0, // UINT32 wr1, UINT32 lenwr1, // UINT32 wr2, UINT32 lenwr2, // UINT32 wr3, UINT32 lenwr3){ // unsigned int i, j, wr[4], len[4]; // const char *opcode; // char oponstack, opcontrol; // wr[0]=wr0; wr[1]=wr1; wr[2]=wr2; wr[3]=wr3; // len[0]=lenwr0; len[1]=lenwr1; len[2]=lenwr2; len[3]=lenwr3; // opcode = OPCODE_StringShort(op).c_str(); // oponstack = !(strcmp(opcode,"PUSH") && // strcmp(opcode,"POP") && // strcmp(opcode,"CALL_NEAR") && // strcmp(opcode,"RET_NEAR")); // opcontrol = (opcode[0]=='J') || !strcmp(opcode,"CALL_NEAR") // || !strcmp(opcode,"RET_NEAR") // || !strcmp(opcode,"SYSCALL"); // for (i=0;i<nw;i++){ // // if (oponstack && (wr[i]==RSP)) continue; // // if (opcontrol && (wr[i]==RIP)) continue; // #if defined(TARGET_IA32E) // // if (oponstack && (instr.wr[i].num==REG_RSP)) continue; // // if (opcontrol && (instr.wr[i].num==REG_RIP)) continue; // if (oponstack && (wr[i]==RSP)) continue; // if (opcontrol && (wr[i]==RIP)) continue; // #else // if (oponstack && (wr[i]==ESP)) continue; // if (opcontrol && (wr[i]==RIP)) continue; // #endif // for (j=0;j<len[i];j++){ // rat[wr[i]+j]=c; // nbwrite[wr[i]+j]++; // } // } // } // uint32_t IlpHistogram::readfromreg(UINT32 nr, // UINT32 rr0, UINT32 lenrr0, // UINT32 rr1, UINT32 lenrr1, // UINT32 rr2, UINT32 lenrr2, // UINT32 rr3, UINT32 lenrr3){ // uint32_t cmax, c; // unsigned int i, j, rr[4], len[4]; // rr[0]=rr0; rr[1]=rr1; rr[2]=rr2; rr[3]=rr3; // len[0]=lenrr0; len[1]=lenrr1; len[2]=lenrr2; len[3]=lenrr3; // cmax=0; // for (i=0;i<nr;i++){ // #ifdef DEBUG1 // fprintf(fd, "instruction %ld: read from reg %s\n", numinst, regx862string(rr[i], len[i])); // #endif // for (j=0;j<len[i];j++){ // cmax=((c=rat[rr[i]+j])>cmax)?c:cmax; // } // } // for (i=0;i<nr;i++){ // for (j=0;j<len[i];j++){ // nbread[rr[i]+j]++; // } // } // return cmax; // } uint32_t IlpHistogram::readfrommem(ADDRINT amr, UINT32 rsize){ return memory.ReadMemory(amr,rsize); } VOID IlpHistogram::writetomem(uint32_t cexe, ADDRINT amw, UINT32 wsize){ memory.WriteMemory(cexe, amw, wsize); } //////////////////////////////////////////////////////////////// // CLASS ROUTINEPROFILE //////////////////////////////////////////////////////////////// RoutineHistogram::RoutineHistogram(const char *nname, const char *image, ADDRINT addr, RTN rtn, IlptoolInterface *ilp): RoutineInterface(nname, image, addr, rtn, 0, 0, 0, NULL) { rtn_name = nname; // if (ilp) // call_vector.push_back(ilp); } RoutineHistogram::~RoutineHistogram() {} void RoutineHistogram::start() { if (ctrl_start()) { IlptoolInterface *new_ilp = new IlpHistogram(this->rtn_name.c_str(), this->call_depth, this->call_id); (IlpList.back())->next_ilp = new_ilp; IlpList.push_back(new_ilp); // call_vector.push_back(new_ilp); outfile << setw(call_depth*5) << ""; outfile << "start : " << setw(1) << "<" /*<< rtn_image << ":"*/ << rtn_name << ">" << setw(10) << " (depth: "<< call_depth << ", lcid: "<< local_cid << ")" << endl; // XML Output outxml << setw(call_depth*5) << ""; outxml << "<call name=\""<< rtn_name //<< "\" call_id=\""<< call_id <<"\" >" << endl; outxml << setw(call_depth*5) << ""; // outxml << "<call_id>" << call_id++ << "</call_id>" << endl; //#define DEBUG_ILP_VEC 1 #ifdef DEBUG_ILP_VEC cerr << "----------DEBUG_ILP_VEC--CTRL_START--Start- " << rtn_image << "|" << rtn_name <<" ---- depth: "<< call_depth << "--- rtn_s_d: "<< rtn_start_depth << endl; for (unsigned int i=0; i<IlpList.size(); i++) cerr << " IlpList[" << i << "] = "<< IlpList[i] << " (" << IlpList[i]->name << ")" << endl; cerr << endl; cerr << "----------DEBUG_ILP_VEC--CTRL_START--Stop------------" << endl; #endif // outfile << setw(call_depth*5) << ""; // outfile << "start : " << setw(15) << rtn_name << setw(10) << " (depth: "<< call_depth << setw(10) << "rtn_s_d: "<< rtn_start_depth << ")" << endl; } } void RoutineHistogram::stop() { IlpHistogram *tmpilp=0; if(ctrl_stop()) { // FIND FUNCTION which is STOP into IlpList vector. unsigned int i; unsigned int count=0; for (i=IlpList.size()-1; i>0; i--) { if (rtn_name == IlpList[i]->name) break; count++; } if (count == IlpList.size()-1 ) { outfile << setw((call_depth+1)*5) << ""; outfile << "imp. stop ?: " << setw(1) << "<" << rtn_name << "> (cid: " // outfile << "imp. stop ?: " << setw(1) << "<" << (IlpList.back())->name << "> (cid: " << (IlpList.back())->call_id << ") " << "> (lcid: " << local_cid << ") "; tmpilp = (IlpHistogram *)(IlpList.back()); tmpilp->dump(outfile); tmpilp->dumpxml(outxml, call_depth+1); outfile << endl; call_depth++; } else if (count>0) { // unsigned int j; // if (count>0) { // for (j=IlpList.size()-1; j>i; j--) for (unsigned int j=0; j<count; j++ ) { outfile << setw((call_depth+1)*5) << ""; outfile << "imp. stop: " << setw(1) << "<" << (IlpList.back())->name<< "> (cid: " << (IlpList.back())->call_id << ") " << "> (lcid: " << local_cid << ") "; tmpilp = (IlpHistogram *)(IlpList.back()); tmpilp->dump(outfile); tmpilp->dumpxml(outxml, call_depth+1); outfile << endl; (IlpList.back())->stop(); IlpList.pop_back(); delete tmpilp; (IlpList.back())->next_ilp = NULL; } //call_depth++; } // Perform the explicite STOP outfile << setw((call_depth+1)*5) << ""; outfile << "stop : " << setw(1) << "<" << rtn_name << ">" ; outfile << " (depth: "<< (call_depth+1) << ", lcid: "<< local_cid <<")";// << " rtn_s_d: "<< rtn_start_depth << ")";// << endl; // XML Output outxml << setw((call_depth+2)*5) << ""; outxml << "<name>"<< rtn_name << "</name>"<<endl; outxml << setw((call_depth+2)*5) << ""; outxml << "<cid>"<< (IlpList.back())->call_id << "</cid>"<<endl; outxml << setw((call_depth+2)*5) << ""; outxml << "<depth>"<< call_depth+1 << "</depth>"<<endl; if (IlpList.size()>1) { tmpilp = (IlpHistogram *)IlpList.back(); tmpilp->dump(outfile); tmpilp->dumpxml(outxml, call_depth+1); outfile << endl; } outxml << setw((call_depth+1)*5) << ""; outxml << "</call>" << endl; if(IlpList.size()>1) { (IlpList.back())->stop(); IlpList.pop_back(); delete tmpilp; if (IlpList.size()>0) (IlpList.back())->next_ilp = NULL; } } else { // if (count) outfile << setw((call_depth+1)*5) << ""; outfile << "stop : " << setw(1) << "<" << rtn_name << ">" ; outfile << " (depth: "<< (call_depth+1) << ", lcid: "<< local_cid <<")";// << " rtn_s_d: "<< rtn_start_depth << ")";// << endl; // XML Output outxml << setw((call_depth+2)*5) << ""; outxml << "<name>"<< rtn_name << "</name>"<<endl; outxml << setw((call_depth+2)*5) << ""; outxml << "<cid>"<< (IlpList.back())->call_id << "</cid>"<<endl; outxml << setw((call_depth+2)*5) << ""; outxml << "<depth>"<< call_depth+1 << "</depth>"<<endl; if (IlpList.size()>1) { tmpilp = (IlpHistogram *)IlpList.back(); tmpilp->dump(outfile); tmpilp->dumpxml(outxml, call_depth+1); outfile << endl; } outxml << setw((call_depth+1)*5) << ""; outxml << "</call>" << endl; if(IlpList.size()>1) { (IlpList.back())->stop(); IlpList.pop_back(); delete tmpilp; if (IlpList.size()>0) (IlpList.back())->next_ilp = NULL; } } #ifdef DEBUG_ILP_VEC // cerr << "----------DEBUG_ILP_VEC---CTRL_STOP-- Start- " << rtn_name <<" -----------" << endl; cerr << "----------DEBUG_ILP_VEC--CTRL_STOP--Start- " << rtn_image << "|" << rtn_name <<" ---- depth: "<< call_depth << "--- rtn_s_d: "<< rtn_start_depth << endl; // for (unsigned int i=0; i<call_vector.size(); i++) // cerr << "call_vector["<< i << "] = " << call_vector[i] << endl;; // cerr << endl; for (unsigned int i=0; i<IlpList.size(); i++) cerr << " IlpList[" << i << "] = "<< IlpList[i] << " (" << IlpList[i]->name << ")"<< endl; // cerr << "This routine : " << rtn_image << "|" << rtn_name << " " << endl; cerr << endl; cerr << "----------DEBUG_ILP_VEC---CTRL_STOP-- Stop ------------" << endl; #endif } }
Pilp5/tools/histogram.hh
:
#ifndef HISTOGRAM_HH #define HISTOGRAM_HH #include <iostream> #include <vector> #include <stdint.h> #include "config.hh" extern "C" { #include "xed-category-enum.h" } using std::ostream; using std::vector; class Histogram{ public: Histogram(); void update(uint32_t cycle, xed_category_enum_t category); void dump(ostream &os, uint32_t nbcycles, ostream &colorfile); void sdump(ostream &os, uint32_t nbcycles); void resize(uint32_t size); private: vector<uint32_t> histogram[XED_CATEGORY_LAST]; uint32_t total[XED_CATEGORY_LAST]; #ifdef SHORT_HISTO vector<uint32_t> shisto; uint32_t size; static const uint32_t shsize=1024; #endif }; #endif // HISTOGRAM_HH
Pilp5/tools/histogram.cpp
:
#include <iostream> //#include <iomanip> #include "histogram.hh" #include "config.hh" #include <cstdlib> using std::cerr; using std::endl; using std::hex; using std::dec; Histogram::Histogram()//: size(0) { //this->resize(size); } void Histogram::update(uint32_t cycle, xed_category_enum_t category) { if(cycle>histogram[category].capacity()) { cerr << "DEBUG("<<hex<<this<<dec<<") Error: histogram length too short !!! (cycle: "<< cycle <<")" << endl; abort(); } histogram[category][cycle]++; total[category]++; #ifdef SHORT_HISTO uint32_t scycle = (cycle * shsize) / size; if (scycle>shisto.capacity()) { cerr << "DEBUG("<<hex<<this<<dec<<") Error: shisto length too short !!! (scycle: "<< scycle <<")" << endl; abort(); } shisto[scycle]++; #endif } void Histogram::dump(ostream &os, uint32_t nbcycles, ostream &colorfile) { os << "Cycles"; for(unsigned int j=0; j<XED_CATEGORY_LAST; j++) { if (total[j]>0) { os << "\t" << xed_category_enum_t2str((xed_category_enum_t)j); } } os << endl; for(unsigned int i=0; i<= nbcycles; i++) { os << i; for(unsigned int j=0; j<XED_CATEGORY_LAST; j++) { if (total[j]>0) { os << "\t" << histogram[j][i]; } } os << endl; } for(unsigned int j=0; j<XED_CATEGORY_LAST; j++) { if(total[j]) { colorfile << "1" << endl; } else { colorfile << "0" << endl; } } } void Histogram::sdump(ostream &os, uint32_t nbcycles) { #ifdef SHORT_HISTO os << "Cycles"; os << "\t" << "Instructions"; os << endl; for(unsigned int i=0; i<= shsize; i++) { os << i; os << "\t" << shisto[i]*shsize/size; os << endl; } #endif } void Histogram::resize(uint32_t new_size) { for(unsigned int j=0; j<XED_CATEGORY_LAST; j++) { histogram[j].resize(new_size,0); total[j] = 0; } #ifdef SHORT_HISTO size = new_size; shisto.resize(shsize+1,0); #endif }
Trace analysis
Pilp5/tools/ilptrace.hh
:
#ifndef ILPTRACE_HH #define ILPTRACE_HH #include "pin.H" #include "ilptool_interface.hh" #include "ilpcommon.hh" #include "utils/memory.hh" #include "utils/memory.tcc" #include "tools/trace.hh" extern "C" { #include "xed-category-enum.h" } class IlpTrace: public IlptoolInterface{ protected: Memory<unsigned long> memory; Memory<unsigned long> memory_trace; uint32_t rat[REG_FILE_SIZE], nbread[REG_FILE_SIZE], nbwrite[REG_FILE_SIZE], npg; uint32_t rat_trace[REG_FILE_SIZE]; public: bool is_main; public: uint32_t nbcycles; uint32_t numinst; uint32_t nbcycles_control; uint32_t numinst_control; public: Trace trace; public: IlpTrace(const char *nickname, uint32_t dh, uint32_t cid); ~IlpTrace(); // IlptoolInterface void instrument(INS ins, VOID *v); void analyse(Instruction &instr); void dump(ostream &os); void dumpxml(ostream &os, int depth); void stop(); bool stoped; }; // END of CLASS: IlpTrace // CLASS ROUTINE PROFILE IMPLEMENTS ROUTINE INTERFACE class RoutineTrace: public RoutineInterface{ public: RoutineTrace(const char *name, const char *image, ADDRINT addr, RTN rtn, IlptoolInterface *ilp); ~RoutineTrace(); // RoutineInterface virtual void start(); virtual void stop(); protected: string rtn_name; string rtn_image; ADDRINT rtn_address; RTN rtn_rtn; UINT64 rtn_rtnCount; UINT64 rtn_depth_counter; UINT64 rtn_start_depth; bool is_rtn_starting_instrumentation; public: vector<IlptoolInterface *> call_vector; }; #endif
Pilp5/tools/ilptrace.cpp
:
extern "C" { #include "xed-interface.h" #include "xed-immdis.h" #include "xed-portability.h" } #include "pin.H" #include "tools/ilptrace.hh" #include "instrument.hh" #include <iostream> #include <sstream> #include <iomanip> #include "options.hh" #include "extern.hh" using std::cerr; using std::endl; using std::stringstream; //////////////////////////////////////////////////////////////// // CLASS ILPHISTOGRAM //////////////////////////////////////////////////////////////// IlpTrace::IlpTrace(const char *nickname, uint32_t dh, uint32_t cid):IlptoolInterface(nickname, dh, cid), trace() { unsigned long i; for (i=0;i<REG_FILE_SIZE;i++){ rat[i]=0; rat_trace[i]=0; nbread[i]=0; nbwrite[i]=0; } nbcycles=0; npg=0; numinst=0; nbcycles_control=0; numinst_control=0; memory.Reset(); memory_trace.Reset(); stoped = false; is_main = false; name = nickname; if(options.option_list["command"]=="trace") { trace.resize((uint32_t)atoi(options.option_list["length"].c_str())+1); } } IlpTrace::~IlpTrace() {} /////////////////////////////////////////////////////////// ////////// START OF /// ILP COMPUTE FUNCTIONS ///////////// /////////////////////////////////////////////////////////// VOID IlpTrace::analyse(Instruction &instr) { uint32_t c1,cexe; uint32_t rdep[Instruction::MAXRRDEP] = {0, 0, 0, 0, 0, 0, 0, 0}; uint32_t mdep[Instruction::MAXRRDEP] = {0, 0, 0, 0, 0, 0, 0, 0}; uint32_t nbrdep; uint32_t nbmdep = 0, m, i, j, k=0,l,r; if(!stoped) { numinst++; //#define DEBUG_ANALYSE 1 #ifdef DEBUG_ANALYSE if (instr.nbr>Instruction::MAXRRDEP) { cerr << "ERROR instruction have too many sources !!!" << endl; // cerr << instr << endl; instr.dump(cerr); cerr << endl; abort(); } #endif for(i=0; i<instr.nbr; i++){ for (j=0;j<instr.rr[i].len;j++){ r=rat_trace[instr.rr[i].num+j]; for(l=0;l<k;l++) if (r==rdep[l]) break; if (l==k){ if (k<Instruction::MAXRRDEP){rdep[k]=r;k++;} else { cerr << "too many rdeps" << endl; abort();} } } } nbrdep=k; k=0; if (instr.amr){ for(i=0; i<instr.rsize; i++){ m=memory_trace.ReadMemory(instr.amr+i, 1); for(j=0; j<k; j++) if (m==mdep[j]) break; if (j==k){ if (k<Instruction::MAXRRDEP) {mdep[k]=m;k++;} else { cerr << "too many mdeps" << endl; abort();} } } } if (instr.amr2){ for(i=0; i<instr.rsize; i++){ m=memory_trace.ReadMemory(instr.amr2+i, 1); for(j=0; j<k; j++) if (m==mdep[j]) break; if (j==k){ if (k<Instruction::MAXRRDEP) {mdep[k]=m;k++;} else { cerr << "too many mdeps" << endl; abort();} } } } nbmdep=k; // CYCLE COMPUTATION stringstream tkey; tkey << hex << instr.address << dec; cexe = 0; for(i=0; i<nbrdep; i++) { c1 = trace[rdep[i]].get_cycle(); cexe = (c1>cexe)?c1:cexe; // nbrdep++; tkey << ":" << hex << trace[rdep[i]].get_address() << dec; } for(i=0; i<nbmdep; i++){ c1 = trace[mdep[i]].get_cycle(); cexe = (c1>cexe)?c1:cexe; tkey << ":" << hex << trace[mdep[i]].get_address() << dec; } cexe++; nbcycles=(cexe>nbcycles)?cexe:nbcycles; // Write to registers //#define DEBUG_ANALYSE 1 #ifdef DEBUG_ANALYSE if (instr.nbw>Instruction::MAXWRDEP) { cerr << "ERROR instruction have too many destinations !!!" << endl; instr.dump(cerr); cerr << endl; abort(); } #endif // TRACE UPDATE Operation operation(instr.is_control, numinst, cexe, instr.address, instr.opcode, nbrdep, rdep, nbmdep, mdep, instr.xed_category, tkey.str().c_str()); if (nbmdep != operation.get_nbmdep() ) { cerr << "DEBUG NBMDEP : nbmdep = " << nbmdep << endl; cerr << "DEBUG NBMDEP : get nbmdep = " << operation.get_nbmdep() << endl; cerr << "DEBUG NBMDEP : get nbrdep = " << operation.get_nbrdep() << endl; cerr << endl; } trace.update(operation, numinst); if (instr.is_control) trace.update_control(numinst,&numinst_control,&nbcycles_control); const char *opcode; char oponstack, opcontrol; opcode = OPCODE_StringShort(instr.opcode).c_str(); oponstack = !(strcmp(opcode,"PUSH") && strcmp(opcode,"POP") && strcmp(opcode,"CALL_NEAR") && strcmp(opcode,"RET_NEAR")); opcontrol = (opcode[0]=='J') || !strcmp(opcode,"CALL_NEAR") || !strcmp(opcode,"RET_NEAR") || !strcmp(opcode,"SYSCALL"); for(i=0; i<instr.nbw; i++) { #if defined(TARGET_IA32E) if (oponstack && (instr.wr[i].num==RSP)) continue; if (opcontrol && (instr.wr[i].num==RIP)) continue; #else if (oponstack && (instr.wr[i].num==ESP)) continue; if (opcontrol && (instr.wr[i].num==RIP)) continue; #endif for (j=0;j<instr.wr[i].len;j++){ rat_trace[instr.wr[i].num+j]=numinst; rat[instr.wr[i].num+j]=cexe; } } if(instr.amw) memory_trace.WriteMemory(numinst, instr.amw, instr.wsize); } if (next_ilp) next_ilp->analyse(instr); } /////////////////////////////////////////////////////////// ////////// END OF /// ILP COMPUTE FUNCTIONS /////////////// /////////////////////////////////////////////////////////// // Pin calls this function every time a new instruction is encountered VOID IlpTrace::instrument(INS ins, VOID *v) { UINT32 nr, nw, i; OPCODE op; Register rr[8], wr[8]; IlpTrace *this_or_next = this; bool is_float=false; /* if ( INS_RepPrefix(ins) || INS_RepnePrefix(ins) ) { // WARNING DO NOT USE REP Prefixed INSTRUCTION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! xed_decoded_inst_t* xedd = INS_XedDec(ins); // xed_operand_values_t* xedv = INS_xed_operand_values(ins); xed_operand_values_t* xedv = xed_decoded_inst_operands(xedd); bool real_rep = xed_operand_values_has_real_rep(xedv); if (real_rep) { // you have a 'real' rep prefix cerr << "REP prefix detected and not supported yet !!!" << endl; cerr << "Instruction address: " << hex << a << dec << endl; cerr << INS_Disassemble(ins).c_str() << endl; abort(); } } */ op = INS_Opcode(ins); nr = INS_MaxNumRRegs(ins); if(nr>8) { cerr << "NR > 8 !!!" <<endl; abort(); } for (i=0; i<nr; i++){ rr[i].num = reg2int(INS_RegR(ins, i), &rr[i].len); if (REG_is_fr(INS_RegR(ins, i))) is_float=true; if (rr[i].num > 10000) { cerr << "RR > 10000 !!!" <<endl; abort(); } } nw = INS_MaxNumWRegs(ins); if(nw>8) { cerr << "NW > 8 !!!" <<endl; abort(); } for (i=0; i<nw; i++){ wr[i].num = reg2int(INS_RegW(ins, i), &wr[i].len); if (REG_is_fr(INS_RegW(ins, i))) is_float=true; if (wr[i].num > 10000) { cerr << "WR > 10000 !!!: " << wr[i].num << endl; cerr << hex << INS_Address(ins) << dec << "\t" << INS_Mnemonic(ins) << endl; cerr << hex << INS_Address(ins) << dec << "\t" << INS_Disassemble(ins) << endl; abort(); } } UINT32 xed_category = INS_Category(ins); bool is_control; if (INS_IsBranchOrCall(ins)) is_control=true; else is_control=false; if ((options.option_list["floatonly"]=="0") || is_float) { if (INS_IsMemoryRead(ins) && INS_HasMemoryRead2(ins) && INS_IsMemoryWrite(ins)) INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(InstrumentAnalyse), IARG_PTR, this_or_next, IARG_INST_PTR, IARG_BOOL, (BOOL)is_control, IARG_UINT32, (UINT32)op, IARG_UINT32, nr, IARG_UINT32, nw, IARG_UINT32, rr[0].num, IARG_UINT32, rr[0].len, IARG_UINT32, rr[1].num, IARG_UINT32, rr[1].len, IARG_UINT32, rr[2].num, IARG_UINT32, rr[2].len, IARG_UINT32, rr[3].num, IARG_UINT32, rr[3].len, IARG_UINT32, rr[4].num, IARG_UINT32, rr[4].len, IARG_UINT32, rr[5].num, IARG_UINT32, rr[5].len, IARG_UINT32, rr[6].num, IARG_UINT32, rr[6].len, IARG_UINT32, rr[7].num, IARG_UINT32, rr[7].len, IARG_UINT32, wr[0].num, IARG_UINT32, wr[0].len, IARG_UINT32, wr[1].num, IARG_UINT32, wr[1].len, IARG_UINT32, wr[2].num, IARG_UINT32, wr[2].len, IARG_UINT32, wr[3].num, IARG_UINT32, wr[3].len, IARG_UINT32, wr[4].num, IARG_UINT32, wr[4].len, IARG_UINT32, wr[5].num, IARG_UINT32, wr[5].len, IARG_UINT32, wr[6].num, IARG_UINT32, wr[6].len, IARG_UINT32, wr[7].num, IARG_UINT32, wr[7].len, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_MEMORYREAD2_EA, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_UINT32, xed_category, IARG_END); else if (INS_IsMemoryRead(ins) && INS_HasMemoryRead2(ins)) INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(InstrumentAnalyse), IARG_PTR, this_or_next, IARG_INST_PTR, IARG_BOOL, (BOOL)is_control, IARG_UINT32, (UINT32)op, IARG_UINT32, nr, IARG_UINT32, nw, IARG_UINT32, rr[0].num, IARG_UINT32, rr[0].len, IARG_UINT32, rr[1].num, IARG_UINT32, rr[1].len, IARG_UINT32, rr[2].num, IARG_UINT32, rr[2].len, IARG_UINT32, rr[3].num, IARG_UINT32, rr[3].len, IARG_UINT32, rr[4].num, IARG_UINT32, rr[4].len, IARG_UINT32, rr[5].num, IARG_UINT32, rr[5].len, IARG_UINT32, rr[6].num, IARG_UINT32, rr[6].len, IARG_UINT32, rr[7].num, IARG_UINT32, rr[7].len, IARG_UINT32, wr[0].num, IARG_UINT32, wr[0].len, IARG_UINT32, wr[1].num, IARG_UINT32, wr[1].len, IARG_UINT32, wr[2].num, IARG_UINT32, wr[2].len, IARG_UINT32, wr[3].num, IARG_UINT32, wr[3].len, IARG_UINT32, wr[4].num, IARG_UINT32, wr[4].len, IARG_UINT32, wr[5].num, IARG_UINT32, wr[5].len, IARG_UINT32, wr[6].num, IARG_UINT32, wr[6].len, IARG_UINT32, wr[7].num, IARG_UINT32, wr[7].len, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_MEMORYREAD2_EA, IARG_ADDRINT, 0L, IARG_UINT32, 0, IARG_UINT32, xed_category, IARG_END); else if (INS_IsMemoryRead(ins) && INS_IsMemoryWrite(ins)) INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(InstrumentAnalyse), IARG_PTR, this_or_next, IARG_INST_PTR, IARG_BOOL, (BOOL)is_control, IARG_UINT32, (UINT32)op, IARG_UINT32, nr, IARG_UINT32, nw, IARG_UINT32, rr[0].num, IARG_UINT32, rr[0].len, IARG_UINT32, rr[1].num, IARG_UINT32, rr[1].len, IARG_UINT32, rr[2].num, IARG_UINT32, rr[2].len, IARG_UINT32, rr[3].num, IARG_UINT32, rr[3].len, IARG_UINT32, rr[4].num, IARG_UINT32, rr[4].len, IARG_UINT32, rr[5].num, IARG_UINT32, rr[5].len, IARG_UINT32, rr[6].num, IARG_UINT32, rr[6].len, IARG_UINT32, rr[7].num, IARG_UINT32, rr[7].len, IARG_UINT32, wr[0].num, IARG_UINT32, wr[0].len, IARG_UINT32, wr[1].num, IARG_UINT32, wr[1].len, IARG_UINT32, wr[2].num, IARG_UINT32, wr[2].len, IARG_UINT32, wr[3].num, IARG_UINT32, wr[3].len, IARG_UINT32, wr[4].num, IARG_UINT32, wr[4].len, IARG_UINT32, wr[5].num, IARG_UINT32, wr[5].len, IARG_UINT32, wr[6].num, IARG_UINT32, wr[6].len, IARG_UINT32, wr[7].num, IARG_UINT32, wr[7].len, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_ADDRINT, 0L, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_UINT32, xed_category, IARG_END); else if (INS_IsMemoryRead(ins)) INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(InstrumentAnalyse), IARG_PTR, this_or_next, IARG_INST_PTR, IARG_BOOL, (BOOL)is_control, IARG_UINT32, (UINT32)op, IARG_UINT32, nr, IARG_UINT32, nw, IARG_UINT32, rr[0].num, IARG_UINT32, rr[0].len, IARG_UINT32, rr[1].num, IARG_UINT32, rr[1].len, IARG_UINT32, rr[2].num, IARG_UINT32, rr[2].len, IARG_UINT32, rr[3].num, IARG_UINT32, rr[3].len, IARG_UINT32, rr[4].num, IARG_UINT32, rr[4].len, IARG_UINT32, rr[5].num, IARG_UINT32, rr[5].len, IARG_UINT32, rr[6].num, IARG_UINT32, rr[6].len, IARG_UINT32, rr[7].num, IARG_UINT32, rr[7].len, IARG_UINT32, wr[0].num, IARG_UINT32, wr[0].len, IARG_UINT32, wr[1].num, IARG_UINT32, wr[1].len, IARG_UINT32, wr[2].num, IARG_UINT32, wr[2].len, IARG_UINT32, wr[3].num, IARG_UINT32, wr[3].len, IARG_UINT32, wr[4].num, IARG_UINT32, wr[4].len, IARG_UINT32, wr[5].num, IARG_UINT32, wr[5].len, IARG_UINT32, wr[6].num, IARG_UINT32, wr[6].len, IARG_UINT32, wr[7].num, IARG_UINT32, wr[7].len, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_ADDRINT, 0L, IARG_ADDRINT, 0L, IARG_UINT32, 0, IARG_UINT32, xed_category, IARG_END); else if (INS_IsMemoryWrite(ins)) INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(InstrumentAnalyse), IARG_PTR, this_or_next, IARG_INST_PTR, IARG_BOOL, (BOOL)is_control, IARG_UINT32, (UINT32)op, IARG_UINT32, nr, IARG_UINT32, nw, IARG_UINT32, rr[0].num, IARG_UINT32, rr[0].len, IARG_UINT32, rr[1].num, IARG_UINT32, rr[1].len, IARG_UINT32, rr[2].num, IARG_UINT32, rr[2].len, IARG_UINT32, rr[3].num, IARG_UINT32, rr[3].len, IARG_UINT32, rr[4].num, IARG_UINT32, rr[4].len, IARG_UINT32, rr[5].num, IARG_UINT32, rr[5].len, IARG_UINT32, rr[6].num, IARG_UINT32, rr[6].len, IARG_UINT32, rr[7].num, IARG_UINT32, rr[7].len, IARG_UINT32, wr[0].num, IARG_UINT32, wr[0].len, IARG_UINT32, wr[1].num, IARG_UINT32, wr[1].len, IARG_UINT32, wr[2].num, IARG_UINT32, wr[2].len, IARG_UINT32, wr[3].num, IARG_UINT32, wr[3].len, IARG_UINT32, wr[4].num, IARG_UINT32, wr[4].len, IARG_UINT32, wr[5].num, IARG_UINT32, wr[5].len, IARG_UINT32, wr[6].num, IARG_UINT32, wr[6].len, IARG_UINT32, wr[7].num, IARG_UINT32, wr[7].len, IARG_ADDRINT, 0L, IARG_UINT32, 0, IARG_ADDRINT, 0L, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_UINT32, xed_category, IARG_END); else INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(InstrumentAnalyse), IARG_PTR, this_or_next, IARG_INST_PTR, IARG_BOOL, (BOOL)is_control, IARG_UINT32, (UINT32)op, IARG_UINT32, nr, IARG_UINT32, nw, IARG_UINT32, rr[0].num, IARG_UINT32, rr[0].len, IARG_UINT32, rr[1].num, IARG_UINT32, rr[1].len, IARG_UINT32, rr[2].num, IARG_UINT32, rr[2].len, IARG_UINT32, rr[3].num, IARG_UINT32, rr[3].len, IARG_UINT32, rr[4].num, IARG_UINT32, rr[4].len, IARG_UINT32, rr[5].num, IARG_UINT32, rr[5].len, IARG_UINT32, rr[6].num, IARG_UINT32, rr[6].len, IARG_UINT32, rr[7].num, IARG_UINT32, rr[7].len, IARG_UINT32, wr[0].num, IARG_UINT32, wr[0].len, IARG_UINT32, wr[1].num, IARG_UINT32, wr[1].len, IARG_UINT32, wr[2].num, IARG_UINT32, wr[2].len, IARG_UINT32, wr[3].num, IARG_UINT32, wr[3].len, IARG_UINT32, wr[4].num, IARG_UINT32, wr[4].len, IARG_UINT32, wr[5].num, IARG_UINT32, wr[5].len, IARG_UINT32, wr[6].num, IARG_UINT32, wr[6].len, IARG_UINT32, wr[7].num, IARG_UINT32, wr[7].len, IARG_ADDRINT, 0L, IARG_UINT32, 0, IARG_ADDRINT, 0L, IARG_ADDRINT, 0L, IARG_UINT32, 0, IARG_UINT32, xed_category, IARG_END); } } void IlpTrace::dump(ostream &os) { os << "::I[" << numinst << "]"; os << "::C[" << nbcycles << "]"; os << "::ILP[" << (double)numinst/(double)nbcycles << "]" ; os << "::Ictrl[" << numinst_control << "]"; os << "::Cctrl[" << nbcycles_control << "]"; os << "::ILPctrl[" << (double)numinst_control/(double)nbcycles_control << "]" ; if(options.option_list["command"]=="trace") { static int version = 0; stringstream filename; filename << options.option_list["resdir"] << "/"; filename << name << "_trace_depth_" << RoutineTrace::call_depth+1 << "_cid_" << call_id << "_ilptool.trace" ; version++; ofstream ofile(filename.str().c_str()); ofile.imbue(std::locale::classic()); trace.dump(ofile, numinst); ofile.close(); } } void IlpTrace::dumpxml(ostream &os, int depth) { } void IlpTrace::stop() { stoped = true; } //////////////////////////////////////////////////////////////// // END INTERFACE //////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////// // CLASS ROUTINETRACE //////////////////////////////////////////////////////////////// RoutineTrace::RoutineTrace(const char *nname, const char *image, ADDRINT addr, RTN rtn, IlptoolInterface *ilp): RoutineInterface(nname, image, addr, rtn, 0, 0, 0, NULL) { rtn_name = nname; if (ilp) call_vector.push_back(ilp); } RoutineTrace::~RoutineTrace() {} void RoutineTrace::start() { if (ctrl_start()) { IlptoolInterface *new_ilp = new IlpTrace(this->rtn_name.c_str(), this->call_depth, this->call_id); (IlpList.back())->next_ilp = new_ilp; IlpList.push_back(new_ilp); call_vector.push_back(new_ilp); outfile << setw(call_depth*5) << ""; outfile << "start : " << setw(15) << rtn_name << setw(10) << " (depth: "<< call_depth << setw(10) << "rtn_s_d: "<< rtn_start_depth << ")" << endl; } } void RoutineTrace::stop() { IlpTrace *tmpilp=0; if (ctrl_stop()) { // FIND FUNCTION which is STOP into IlpList vector. unsigned int i; unsigned int count=0; for (i=IlpList.size()-1; i>0; i--) { if (rtn_name == IlpList[i]->name) break; count++; } if (count == IlpList.size()-1 ) { outfile << setw((call_depth+1)*5) << ""; outfile << "imp. stop ?: " << setw(1) << "<" << rtn_name << "> (cid: " << (IlpList.back())->call_id << ") " << "> (lcid: " << local_cid << ") "; tmpilp = (IlpTrace *)(IlpList.back()); tmpilp->dump(outfile); tmpilp->dumpxml(outxml, call_depth+1); outfile << endl; call_depth++; } else if (count>0) { { for (unsigned int j=0; j<count; j++ ) { outfile << setw((call_depth+1)*5) << ""; outfile << "imp. stop: " << setw(1) << "<" << (IlpList.back())->name<< "> (cid: " << (IlpList.back())->call_id << ") " << "> (lcid: " << local_cid << ") "; tmpilp = (IlpTrace *)(IlpList.back()); tmpilp->dump(outfile); tmpilp->dumpxml(outxml, call_depth+1); outfile << endl; (IlpList.back())->stop(); IlpList.pop_back(); delete tmpilp; (IlpList.back())->next_ilp = NULL; } } // Perform the explicite STOP outfile << setw((call_depth+1)*5) << ""; outfile << "stop : " << setw(1) << "<" << rtn_name << ">" ; outfile << " (depth: "<< (call_depth+1) << ", lcid: "<< local_cid <<")";// << " rtn_s_d: "<< rtn_start_depth << ")";// << endl; // XML Output outxml << setw((call_depth+2)*5) << ""; outxml << "<name>"<< rtn_name << "</name>"<<endl; outxml << setw((call_depth+2)*5) << ""; outxml << "<cid>"<< (IlpList.back())->call_id << "</cid>"<<endl; outxml << setw((call_depth+2)*5) << ""; outxml << "<depth>"<< call_depth+1 << "</depth>"<<endl; if (IlpList.size()>1) { tmpilp = (IlpTrace *)IlpList.back(); tmpilp->dump(outfile); tmpilp->dumpxml(outxml, call_depth+1); outfile << endl; } outxml << setw((call_depth+1)*5) << ""; outxml << "</call>" << endl; if(IlpList.size()>1) { (IlpList.back())->stop(); IlpList.pop_back(); delete tmpilp; if (IlpList.size()>0) (IlpList.back())->next_ilp = NULL; } } else { // if (count) outfile << setw((call_depth+1)*5) << ""; outfile << "stop : " << setw(1) << "<" << rtn_name << ">" ; outfile << " (depth: "<< (call_depth+1) << ", lcid: "<< local_cid <<")";// << " rtn_s_d: "<< rtn_start_depth << ")";// << endl; // XML Output outxml << setw((call_depth+2)*5) << ""; outxml << "<name>"<< rtn_name << "</name>"<<endl; outxml << setw((call_depth+2)*5) << ""; outxml << "<cid>"<< (IlpList.back())->call_id << "</cid>"<<endl; outxml << setw((call_depth+2)*5) << ""; outxml << "<depth>"<< call_depth+1 << "</depth>"<<endl; if (IlpList.size()>1) { tmpilp = (IlpTrace *)IlpList.back(); tmpilp->dump(outfile); tmpilp->dumpxml(outxml, call_depth+1); outfile << endl; } outxml << setw((call_depth+1)*5) << ""; outxml << "</call>" << endl; if(IlpList.size()>1) { (IlpList.back())->stop(); IlpList.pop_back(); delete tmpilp; if (IlpList.size()>0) (IlpList.back())->next_ilp = NULL; } } #ifdef DEBUG_ILP_VEC cerr << "----------DEBUG_ILP_VEC--CTRL_STOP--Start- " << rtn_image << "|" << rtn_name <<" ---- depth: "<< call_depth << "--- rtn_s_d: "<< rtn_start_depth << endl; for (unsigned int i=0; i<IlpList.size(); i++) cerr << " IlpList[" << i << "] = "<< IlpList[i] << " (" << IlpList[i]->name << ")"<< endl; cerr << endl; cerr << "----------DEBUG_ILP_VEC---CTRL_STOP-- Stop ------------" << endl; #endif } }
Pilp5/tools/trace.hh
:
#ifndef TRACE_HH #define TRACE_HH #include "pin.H" #include "ilpcommon.hh" extern "C" { #include "xed-category-enum.h" } #include <iostream> using std::ostream; using std::vector; ////////////////////////////////////////// class Operation { public: Operation(); Operation(bool ctrl, uint32_t in, uint32_t cy, ADDRINT addr, UINT32 op, uint32_t nrd, uint32_t *rd, uint32_t nmd, uint32_t *md, xed_category_enum_t category, const char*tkey); bool control; uint32_t get_cycle(); uint32_t get_address(); uint32_t get_nbrdep(); uint32_t get_nbmdep(); uint32_t get_rdep(unsigned int i); uint32_t get_mdep(unsigned int i); void dump(ostream & os); void dumpkeys(ostream & os); private: uint32_t inum; uint32_t cycle; ADDRINT address; UINT32 opcode; uint32_t nbrdep; uint32_t rdep[8]; uint32_t nbmdep; uint32_t mdep[8]; xed_category_enum_t xed_category; string trace_key; }; ///////////////////////////////////////// class Trace { public: Trace(); void update_control(const uint32_t num, uint32_t *numinst_control, uint32_t *nbcycles_control); void update(const Operation &op, const uint32_t num); void dump(ostream &os, uint32_t nbinst); void resize(uint32_t size); Operation &operator [](uint32_t i); private: vector<Operation> operations; }; #endif // TRACE_HH
Pilp5/tools/trace.cpp
:
#include "trace.hh" #include <iomanip> Operation::Operation(): control(false), inum(0), cycle(0), address(0L), opcode(0), nbrdep(0), rdep(), nbmdep(0), mdep(), xed_category(XED_CATEGORY_INVALID) { for(unsigned int i=0; i<8; i++) { rdep[i] = 0; } for(unsigned int i=0; i<8; i++) { mdep[i] = 0; } trace_key = "0"; } Operation::Operation(bool ctrl, uint32_t in, uint32_t cy, ADDRINT addr, UINT32 op, uint32_t nrd, uint32_t *rd, uint32_t nmd, uint32_t *md, xed_category_enum_t category, const char *tkey): control(ctrl), inum(in), cycle(cy), address(addr), opcode(op), nbrdep(nrd), rdep(), nbmdep(nmd), mdep(), xed_category(category), trace_key(tkey) { for(unsigned int i=0; i<nrd; i++) { rdep[i] = rd[i]; } for(unsigned int i=0; i<nmd; i++) { mdep[i] = md[i]; } } uint32_t Operation::get_mdep(unsigned int i) { return mdep[i]; } uint32_t Operation::get_nbmdep() { return nbmdep; } uint32_t Operation::get_rdep(unsigned int i) { return rdep[i]; } uint32_t Operation::get_nbrdep() { return nbrdep; } uint32_t Operation::get_cycle() { return cycle; } uint32_t Operation::get_address() { return address; } void Operation::dump(ostream & os) { os << setw(12) << inum << setw(12) << cycle << setw(15) << setbase(16) << address << setbase(10) << setw(12) << xed_category << setw(12) << xed_category_enum_t2str(xed_category) << setw(12) << setbase(16) << opcode << setbase(10) << setw(20) << OPCODE_StringShort(opcode); unsigned int i; for(i=0; i<nbrdep; i++) os << setw(12) << rdep[i]; for(; i<8; i++) os << setw(12) << "0"; for(i=0; i<nbmdep; i++) os << setw(12) << mdep[i]; for(; i<8; i++) os << setw(12) << "0"; } void Operation::dumpkeys(ostream & os) { os << setw(12) << inum << setw(12) << cycle << setw(15) << setbase(16) << address << setbase(10) << setw(12) << xed_category << setw(12) << xed_category_enum_t2str(xed_category) << setw(12) << setbase(16) << opcode << setbase(10) << setw(20) << OPCODE_StringShort(opcode); unsigned int i; for(i=0; i<nbrdep; i++) os << setw(12) << rdep[i]; for(; i<4; i++) os << setw(12) << "0"; for(i=0; i<nbmdep; i++) os << setw(12) << mdep[i]; for(; i<4; i++) os << setw(12) << "0"; os << setw(50) << trace_key; } Trace::Trace() { } void Trace::update_control(const uint32_t num, uint32_t *numinst_control, uint32_t *nbcycles_control) { uint32_t rd, md; uint32_t nbrd, nbmd, c; unsigned int i; operations[num].control = true; c = operations[num].get_cycle(); (*numinst_control)++; if (c>(*nbcycles_control)) (*nbcycles_control)=c; nbrd = operations[num].get_nbrdep(); for (i=0;i<nbrd;i++){ rd=operations[num].get_rdep(i); if (!(operations[rd].control)) update_control(rd,numinst_control,nbcycles_control); } nbmd = operations[num].get_nbmdep(); for (i=0;i<nbmd;i++){ md=operations[num].get_mdep(i); if (!(operations[md].control)) update_control(md,numinst_control,nbcycles_control); } } void Trace::update(const Operation &op, const uint32_t num) { operations[num] = op; } void Trace::dump(ostream &os, uint32_t nbinst) { for(unsigned int i=0; i< nbinst; i++) { operations[i].dump(os); os << endl; } } void Trace::resize(uint32_t size) { Operation op; operations.resize(size, op); } Operation &Trace::operator[](uint32_t i) { return operations[i]; }
Misc
Pilp5/config.hh
:
#ifndef CONFIG_HH #define CONFIG_HH //#define SHORT_HISTO #endif
Pilp5/extern.hh
:
#ifndef EXTERN_HH #define EXTERN_HH #include <vector> #include <fstream> #include <string> #include "ilptool_interface.hh" #include "options.hh" using std::ofstream; using std::string; extern IlptoolInterface *main_ilp; extern vector<IlptoolInterface *> IlpList; extern ofstream outfile; extern ofstream outxml; extern Options options; //#define SHORT_HISTO extern string MainImageName; #endif // EXTERN_HH
Pilp5/register.hh
:
#ifndef REGISTER_HH #define REGISTER_HH #include "pin.H" //a structure to hold both a register number and its length in bytes typedef struct {UINT32 num; UINT32 len;} Register; //to convert a register number in our numbering system into a string //the length of the register in bytes should be provided const char *regx862string(UINT32 i, UINT32 len); //to convert a register number in our numbering system into a PIN register number REG regx862regpin(UINT32 i); //to convert a PIN register number into a number in our numbering system //the function also provides the register length in bytes UINT32 reg2int(REG r, UINT32 *len); void dump_pin_reg_map(); //the total number of bytes for all the machine registers #define REG_FILE_SIZE 2048 //our numbering of the registers //for every register, define a constant as its number //shared registers should be aligned //e.g. register RAX occupies interval ranging from 16 to 23, and has number 16 // register EAX occupies interval ranging from 20 to 23, and has number 20 // register AX occupies interval ranging from 22 to 23, and has number 22 // register AH occupies interval ranging from 22 to 22, and has number 22 // register AL occupies interval ranging from 23 to 23, and has number 23 //AX and AH have the same number (22) #define RAX 16 #define EAX 20 #define AX 22 #define AH 22 #define AL 23 #define RBX 24 #define EBX 28 #define BX 30 #define BH 30 #define BL 31 #define RCX 32 #define ECX 36 #define CX 38 #define CH 38 #define CL 39 #define RDX 40 #define EDX 44 #define DX 46 #define DH 46 #define DL 47 #define R8 48 #define R8D 52 #define R8W 54 #define R8B 55 #define R9 56 #define R9D 60 #define R9W 62 #define R9B 63 #define R10 64 #define R10D 68 #define R10W 70 #define R10B 71 #define R11 72 #define R11D 76 #define R11W 78 #define R11B 79 #define R12 80 #define R12D 84 #define R12W 86 #define R12B 87 #define R13 88 #define R13D 92 #define R13W 94 #define R13B 95 #define R14 96 #define R14D 100 #define R14W 102 #define R14B 103 #define R15 104 #define R15D 108 #define R15W 110 #define R15B 111 #define RBP 112 #define EBP 116 #define BP 118 #define BPL 119 #define RSI 120 #define ESI 124 #define SI 126 #define SIL 127 #define RDI 128 #define EDI 132 #define DI 134 #define DIL 135 #define RSP 136 #define ESP 140 #define SP 142 #define SPL 143 #define CS 144 #define SS 146 #define DS 148 #define ES 150 #define FS 152 #define GS 154 #define RFLAGS 160 #define EFLAGS 164 #define RIP 168 #define EIP 172 #define MM0 192 #define MM1 208 #define MM2 224 #define MM3 240 #define MM4 256 #define MM5 272 #define MM6 288 #define MM7 304 #define ST0 320 #define ST1 336 #define ST2 352 #define ST3 368 #define ST4 384 #define ST5 400 #define ST6 416 #define ST7 432 #define XMM0 448 #define XMM1 464 #define XMM2 480 #define XMM3 496 #define XMM4 512 #define XMM5 528 #define XMM6 544 #define XMM7 560 #define XMM8 576 #define XMM9 592 #define XMM10 608 #define XMM11 624 #define XMM12 640 #define XMM13 656 #define XMM14 672 #define XMM15 688 #define YMM0 704 #define YMM1 736 #define YMM2 768 #define YMM3 800 #define YMM4 832 #define YMM5 864 #define YMM6 896 #define YMM7 928 #define YMM8 960 #define YMM9 992 #define YMM10 1024 #define YMM11 1056 #define YMM12 1088 #define YMM13 1120 #define YMM14 1152 #define YMM15 1184 #define FPCW 1216 #define FPSW 1218 #define FPTAG_FULL 1220 #define FPTAG 1222 #define FPIP_OFF 1224 #define FPIP_SEL 1228 #define FPOPCODE 1232 #define FPDP_OFF 1236 #define FPDP_SEL 1240 #define CR0 1244 #define CR1 1248 #define CR2 1252 #define CR3 1256 #define CR4 1260 #define MXCSR 1264 #define MXCSRMASK 1268 #endif // REGISTER_HH
Pilp5/register.cpp
:
#include "register.hh" #include <iostream> //to convert an x86 register number (our numbering) into a string //the "len" parameter serves to output a 16-bits matching register name //(len==2) or an 8-bits one (len==1) //in our numbering, these registers share the same number //for example, register AX represents both registers "ax" and "ah" //the reason is that the register name (AX) serves as an address //for the register. AH and AX are assumed to share their leading byte const char *regx862string(UINT32 i, UINT32 len){ switch(i){ case RAX: return "rax"; case EAX: return "eax"; case AX: if (len==2) return "ax"; else return "ah"; case AL: return "al"; case RBX: return "rbx"; case EBX: return "ebx"; case BX: if (len==2) return "bx"; else return "bh"; case BL: return "bl"; case RCX: return "rcx"; case ECX: return "ecx"; case CX: if (len==2) return "cx"; else return "ch"; case CL: return "cl"; case RDX: return "rdx"; case EDX: return "edx"; case DX: if (len==2) return "dx"; else return "dh"; case DL: return "dl"; case R8: return "r8"; case R8D: return "r8d"; case R8W: return "r8w"; case R8B: return "r8b"; case R9: return "r9"; case R9D: return "r9d"; case R9W: return "r9w"; case R9B: return "r9b"; case R10: return "r10"; case R10D: return "r10d"; case R10W: return "r10w"; case R10B: return "r10b"; case R11: return "r11"; case R11D: return "r11d"; case R11W: return "r11w"; case R11B: return "r11b"; case R12: return "r12"; case R12D: return "r12d"; case R12W: return "r12w"; case R12B: return "r12b"; case R13: return "r13"; case R13D: return "r13d"; case R13W: return "r13w"; case R13B: return "r13b"; case R14: return "r14"; case R14D: return "r14d"; case R14W: return "r14w"; case R14B: return "r14b"; case R15: return "r15"; case R15D: return "r15d"; case R15W: return "r15w"; case R15B: return "r15b"; case RBP: return "rbp"; case EBP: return "ebp"; case BP: return "bp"; case BPL: return "bpl"; case RSI: return "rsi"; case ESI: return "esi"; case SI: return "si"; case SIL: return "sil"; case RDI: return "rdi"; case EDI: return "edi"; case DI: return "di"; case DIL: return "dil"; case RSP: return "rsp"; case ESP: return "esp"; case SP: return "sp"; case SPL: return "spl"; case CS: return "cs"; case SS: return "ss"; case DS: return "ds"; case ES: return "es"; case FS: return "fs"; case GS: return "gs"; case RFLAGS: return "rflags"; case RIP: return "rip"; case MM0: return "mm0"; case MM1: return "mm1"; case MM2: return "mm2"; case MM3: return "mm3"; case MM4: return "mm4"; case MM5: return "mm5"; case MM6: return "mm6"; case MM7: return "mm7"; case ST0: return "st(0)"; case ST1: return "st(1)"; case ST2: return "st(2)"; case ST3: return "st(3)"; case ST4: return "st(4)"; case ST5: return "st(5)"; case ST6: return "st(6)"; case ST7: return "st(7)"; case XMM0: return "xmm0"; case XMM1: return "xmm1"; case XMM2: return "xmm2"; case XMM3: return "xmm3"; case XMM4: return "xmm4"; case XMM5: return "xmm5"; case XMM6: return "xmm6"; case XMM7: return "xmm7"; //#if defined(TARGET_IA32E) case XMM8: return "xmm8"; case XMM9: return "xmm9"; case XMM10: return "xmm10"; case XMM11: return "xmm11"; case XMM12: return "xmm12"; case XMM13: return "xmm13"; case XMM14: return "xmm14"; case XMM15: return "xmm15"; case YMM0: return "ymm0"; case YMM1: return "ymm1"; case YMM2: return "ymm2"; case YMM3: return "ymm3"; case YMM4: return "ymm4"; case YMM5: return "ymm5"; case YMM6: return "ymm6"; case YMM7: return "ymm7"; case YMM8: return "ymm8"; case YMM9: return "ymm9"; case YMM10: return "ymm10"; case YMM11: return "ymm11"; case YMM12: return "ymm12"; case YMM13: return "ymm13"; case YMM14: return "ymm14"; case YMM15: return "ymm15"; //#endif case MXCSR: return "mxcsr"; case MXCSRMASK: return "mxcsrmask"; case FPCW: return "fpcw"; case FPSW: return "fpsw"; case FPTAG_FULL: return "fptag_full"; case FPTAG: return "fptag"; case FPIP_OFF: return "fpip_off"; case FPIP_SEL: return "fpip_sel"; case FPOPCODE: return "fpopcode"; case FPDP_OFF: return "fpdp_off"; case FPDP_SEL: return "fpdp_sel"; case CR0: return "cr0"; case CR1: return "cr1"; case CR2: return "cr2"; case CR3: return "cr3"; case CR4: return "cr4"; default: return "unknown"; } } //to convert from our numbering to PIN numbering REG regx862regpin(UINT32 i){ switch(i){ case RAX: case EAX: case AX: case AL: #if defined(TARGET_IA32E) return REG_RAX; #else return REG_EAX; #endif case RBX: case EBX: case BX: case BL: #if defined(TARGET_IA32E) return REG_RBX; #else return REG_EBX; #endif case RCX: case ECX: case CX: case CL: #if defined(TARGET_IA32E) return REG_RCX; #else return REG_ECX; #endif case RDX: case EDX: case DX: case DL: #if defined(TARGET_IA32E) return REG_RDX; #else return REG_EDX; #endif #if defined(TARGET_IA32E) case R8: case R8D: case R8W: case R8B: return REG_R8; case R9: case R9D: case R9W: case R9B: return REG_R9; case R10: case R10D: case R10W: case R10B: return REG_R10; case R11: case R11D: case R11W: case R11B: return REG_R11; case R12: case R12D: case R12W: case R12B: return REG_R12; case R13: case R13D: case R13W: case R13B: return REG_R13; case R14: case R14D: case R14W: case R14B: return REG_R14; case R15: case R15D: case R15W: case R15B: return REG_R15; #endif case RBP: case EBP: case BP: case BPL: #if defined(TARGET_IA32E) return REG_RBP; #else return REG_EBP; #endif case RSI: case ESI: case SI: case SIL: #if defined(TARGET_IA32E) return REG_RSI; #else return REG_ESI; #endif case RDI: case EDI: case DI: case DIL: #if defined(TARGET_IA32E) return REG_RDI; #else return REG_EDI; #endif case RSP: case ESP: case SP: case SPL: #if defined(TARGET_IA32E) return REG_RSP; #else return REG_ESP; #endif case CS: return REG_SEG_CS; case SS: return REG_SEG_SS; case DS: return REG_SEG_DS; case ES: return REG_SEG_ES; case FS: return REG_SEG_FS; case GS: return REG_SEG_GS; case RFLAGS: #if defined(TARGET_IA32E) return REG_RFLAGS; #else return REG_EFLAGS; #endif case RIP: #if defined(TARGET_IA32E) return REG_RIP; #else return REG_EIP; #endif case MM0: return REG_MM0; case MM1: return REG_MM1; case MM2: return REG_MM2; case MM3: return REG_MM3; case MM4: return REG_MM4; case MM5: return REG_MM5; case MM6: return REG_MM6; case MM7: return REG_MM7; case ST0: return REG_ST0; case ST1: return REG_ST1; case ST2: return REG_ST2; case ST3: return REG_ST3; case ST4: return REG_ST4; case ST5: return REG_ST5; case ST6: return REG_ST6; case ST7: return REG_ST7; case XMM0: return REG_XMM0; case XMM1: return REG_XMM1; case XMM2: return REG_XMM2; case XMM3: return REG_XMM3; case XMM4: return REG_XMM4; case XMM5: return REG_XMM5; case XMM6: return REG_XMM6; case XMM7: return REG_XMM7; #if defined(TARGET_IA32E) case XMM8: return REG_XMM8; case XMM9: return REG_XMM9; case XMM10: return REG_XMM10; case XMM11: return REG_XMM11; case XMM12: return REG_XMM12; case XMM13: return REG_XMM13; case XMM14: return REG_XMM14; case XMM15: return REG_XMM15; case YMM0: return REG_YMM0; case YMM1: return REG_YMM1; case YMM2: return REG_YMM2; case YMM3: return REG_YMM3; case YMM4: return REG_YMM4; case YMM5: return REG_YMM5; case YMM6: return REG_YMM6; case YMM7: return REG_YMM7; case YMM8: return REG_YMM8; case YMM9: return REG_YMM9; case YMM10: return REG_YMM10; case YMM11: return REG_YMM11; case YMM12: return REG_YMM12; case YMM13: return REG_YMM13; case YMM14: return REG_YMM14; case YMM15: return REG_YMM15; #endif case MXCSR: return REG_MXCSR; case MXCSRMASK: return REG_MXCSRMASK; case FPCW: return REG_FPCW; case FPSW: return REG_FPSW; case FPTAG_FULL: return REG_FPTAG_FULL; case FPTAG: return REG_FPTAG; case FPIP_OFF: return REG_FPIP_OFF; case FPIP_SEL: return REG_FPIP_SEL; case FPOPCODE: return REG_FPOPCODE; case FPDP_OFF: return REG_FPDP_OFF; case FPDP_SEL: return REG_FPDP_SEL; case CR0: return REG_CR0; case CR1: return REG_CR1; case CR2: return REG_CR2; case CR3: return REG_CR3; case CR4: return REG_CR4; default: return REG_INVALID_; } } //to convert from PIN numbering to our numbering //the main function result is the register number in our numbering system //the side effect result "len" is the size in bytes of the requested register UINT32 reg2int(REG r, UINT32 *len){ unsigned int reg; reg = (unsigned int)r; switch(r){ case REG_INVALID_: *len=10000; return 10000; #if defined(TARGET_IA32E) case REG_RDI: *len=8; return RDI;//rdi case REG_RSI: *len=8; return RSI;//rsi case REG_RBP: *len=8; return RBP;//rbp case REG_RSP: *len=8; return RSP;//rsp case REG_RBX: *len=8; return RBX;//rbx case REG_RDX: *len=8; return RDX;//rdx case REG_RCX: *len=8; return RCX;//rcx case REG_RAX: *len=8; return RAX;//rax case REG_R8: *len=8; return R8;//r8 case REG_R9: *len=8; return R9;//r9 case REG_R10: *len=8; return R10;//r10 case REG_R11: *len=8; return R11;//r11 case REG_R12: *len=8; return R12;//r12 case REG_R13: *len=8; return R13;//r13 case REG_R14: *len=8; return R14;//r14 case REG_R15: *len=8; return R15;//r15 case REG_RFLAGS: *len=8; return RFLAGS;//rflags case REG_RIP: *len=8; return RIP;//rip #endif case REG_EFLAGS: *len=8; return RFLAGS;//rflags case REG_EIP: *len=8; return RIP;//rip case REG_SEG_CS: *len=2; return CS;//cs case REG_SEG_SS: *len=2; return SS;//ss case REG_SEG_DS: *len=2; return DS;//ds case REG_SEG_ES: *len=2; return ES;//es case REG_SEG_FS: *len=2; return FS;//fs case REG_SEG_GS: *len=2; return GS;//gs case REG_AL: *len=1; return AL;//al case REG_AH: *len=1; return AH;//ah case REG_AX: *len=2; return AX;//ax case REG_CL: *len=1; return CL;//cl case REG_CH: *len=1; return CH;//ch case REG_CX: *len=2; return CX;//cx case REG_DL: *len=1; return DL;//dl case REG_DH: *len=1; return DH;//dh case REG_DX: *len=2; return DX;//dx case REG_BL: *len=1; return BL;//bl case REG_BH: *len=1; return BH;//bh case REG_BX: *len=2; return BX;//bx case REG_BP: *len=2; return BP;//bp case REG_SI: *len=2; return SI;//si case REG_DI: *len=2; return DI;//di case REG_SP: *len=2; return SP;//sp case REG_FLAGS: *len=8; return RFLAGS;//rflags case REG_IP: *len=8; return RIP;//rip case REG_EDI: *len=4; return EDI;//edi #if defined(TARGET_IA32E) case REG_DIL: *len=1; return DIL;//dil #endif case REG_ESI: *len=4; return ESI;//esi #if defined(TARGET_IA32E) case REG_SIL: *len=1; return SIL;//sil #endif case REG_EBP: *len=4; return EBP;//ebp #if defined(TARGET_IA32E) case REG_BPL: *len=1; return BPL;//bpl #endif case REG_ESP: *len=4; return ESP;//esp #if defined(TARGET_IA32E) case REG_SPL: *len=1; return SPL;//spl #endif case REG_EBX: *len=4; return EBX;//ebx case REG_EDX: *len=4; return EDX;//edx case REG_ECX: *len=4; return ECX;//ecx case REG_EAX: *len=4; return EAX;//eax #if defined(TARGET_IA32E) case REG_R8B: *len=1; return R8B;//r8b case REG_R8W: *len=2; return R8W;//r8w case REG_R8D: *len=4; return R8D;//r8d case REG_R9B: *len=1; return R9B;//r9b case REG_R9W: *len=2; return R9W;//r9w case REG_R9D: *len=4; return R9D;//r9d case REG_R10B: *len=1; return R10B;//r10b case REG_R10W: *len=2; return R10W;//r10w case REG_R10D: *len=4; return R10D;//r10d case REG_R11B: *len=1; return R11B;//r11b case REG_R11W: *len=2; return R11W;//r11w case REG_R11D: *len=4; return R11D;//r11d case REG_R12B: *len=1; return R12B;//r12b case REG_R12W: *len=2; return R12W;//r12w case REG_R12D: *len=4; return R12D;//r12d case REG_R13B: *len=1; return R13B;//r13b case REG_R13W: *len=2; return R13W;//r13w case REG_R13D: *len=4; return R13D;//r13d case REG_R14B: *len=1; return R14B;//r14b case REG_R14W: *len=2; return R14W;//r14w case REG_R14D: *len=4; return R14D;//r14d case REG_R15B: *len=1; return R15B;//r15b case REG_R15W: *len=2; return R15W;//r15w case REG_R15D: *len=4; return R15D;//r15d #endif case REG_MM0: *len=16; return MM0;//mm0 case REG_MM1: *len=16; return MM1;//mm1 case REG_MM2: *len=16; return MM2;//mm2 case REG_MM3: *len=16; return MM3;//mm3 case REG_MM4: *len=16; return MM4;//mm4 case REG_MM5: *len=16; return MM5;//mm5 case REG_MM6: *len=16; return MM6;//mm6 case REG_MM7: *len=16; return MM7;//mm7 case REG_XMM0: *len=16; return XMM0;//xmm0 case REG_XMM1: *len=16; return XMM1;//xmm1 case REG_XMM2: *len=16; return XMM2;//xmm2 case REG_XMM3: *len=16; return XMM3;//xmm3 case REG_XMM4: *len=16; return XMM4;//xmm4 case REG_XMM5: *len=16; return XMM5;//xmm5 case REG_XMM6: *len=16; return XMM6;//xmm6 case REG_XMM7: *len=16; return XMM7;//xmm7 #if defined(TARGET_IA32E) case REG_XMM8: *len=16; return XMM8;//xmm8 case REG_XMM9: *len=16; return XMM9;//xmm9 case REG_XMM10: *len=16; return XMM10;//xmm10 case REG_XMM11: *len=16; return XMM11;//xmm11 case REG_XMM12: *len=16; return XMM12;//xmm12 case REG_XMM13: *len=16; return XMM13;//xmm13 case REG_XMM14: *len=16; return XMM14;//xmm14 case REG_XMM15: *len=16; return XMM15;//xmm15 case REG_YMM0: *len=32; return YMM0;//ymm0 case REG_YMM1: *len=32; return YMM1;//ymm0 case REG_YMM2: *len=32; return YMM2;//ymm0 case REG_YMM3: *len=32; return YMM3;//ymm0 case REG_YMM4: *len=32; return YMM4;//ymm0 case REG_YMM5: *len=32; return YMM5;//ymm0 case REG_YMM6: *len=32; return YMM6;//ymm0 case REG_YMM7: *len=32; return YMM7;//ymm0 case REG_YMM8: *len=32; return YMM8;//ymm0 case REG_YMM9: *len=32; return YMM9;//ymm0 case REG_YMM10: *len=32; return YMM10;//ymm0 case REG_YMM11: *len=32; return YMM11;//ymm0 case REG_YMM12: *len=32; return YMM12;//ymm0 case REG_YMM13: *len=32; return YMM13;//ymm0 case REG_YMM14: *len=32; return YMM14;//ymm0 case REG_YMM15: *len=32; return YMM15;//ymm0 #endif case REG_ST0: *len=16; return ST0;//st(0) case REG_ST1: *len=16; return ST1;//st(1) case REG_ST2: *len=16; return ST2;//st(2) case REG_ST3: *len=16; return ST3;//st(3) case REG_ST4: *len=16; return ST4;//st(4) case REG_ST5: *len=16; return ST5;//st(5) case REG_ST6: *len=16; return ST6;//st(6) case REG_ST7: *len=16; return ST7;//st(7) case REG_MXCSR: *len=4; return MXCSR; case REG_MXCSRMASK: *len=4; return MXCSRMASK; case REG_FPCW: *len=2; return FPCW; #if defined(TARGET_IA32E) case 182: *len=2; return FPSW; #else case 120: *len=2; return FPSW; #endif case REG_FPSW: *len=2; return FPSW; case REG_FPTAG_FULL: *len=2; return FPTAG_FULL; case REG_FPTAG: *len=2; return FPTAG; case REG_FPIP_OFF: *len=8; return FPIP_OFF; case REG_FPIP_SEL: *len=4; return FPIP_SEL; case REG_FPOPCODE: *len=2; return FPOPCODE; case REG_FPDP_OFF: *len=8; return FPDP_OFF; case REG_FPDP_SEL: *len=4; return FPDP_SEL; case REG_CR0: *len=4; return CR0; case REG_CR1: *len=4; return CR1; case REG_CR2: *len=4; return CR2; case REG_CR3: *len=4; return CR3; case REG_CR4: *len=4; return CR4; default: *len=10000+reg; return 10000+reg;// } } void dump_pin_reg_map(){ cerr << "REG_INVALID_" << REG_INVALID_ << endl; cerr << "REG_GR_BASE" << REG_GR_BASE << endl; cerr << "REG_RBASE" << REG_RBASE << endl; // cerr << "REG_GBASE" << REG_GBASE << endl; cerr << "REG_EDI" << REG_EDI << endl; cerr << "REG_GDI" << REG_GDI << endl; cerr << "REG_ESI" << REG_ESI << endl; cerr << "REG_GSI" << REG_GSI << endl; cerr << "REG_EBP" << REG_EBP << endl; cerr << "REG_GBP" << REG_GBP << endl; cerr << "REG_ESP" << REG_ESP << endl; cerr << "REG_STACK_PTR" << REG_STACK_PTR << endl; cerr << "REG_EBX" << REG_EBX << endl; cerr << "REG_GBX" << REG_GBX << endl; cerr << "REG_EDX" << REG_EDX << endl; cerr << "REG_GDX" << REG_GDX << endl; cerr << "REG_ECX" << REG_ECX << endl; cerr << "REG_GCX" << REG_GCX << endl; cerr << "REG_EAX" << REG_EAX << endl; cerr << "REG_GAX" << REG_GAX << endl; cerr << "REG_GR_LAST" << REG_GR_LAST << endl; // cerr << "REG_GROT_LAST" << REG_GROT_LAST << endl; cerr << "REG_SEG_BASE" << REG_SEG_BASE << endl; cerr << "REG_SEG_CS" << REG_SEG_CS << endl; cerr << "REG_SEG_SS" << REG_SEG_SS << endl; cerr << "REG_SEG_DS" << REG_SEG_DS << endl; cerr << "REG_SEG_ES" << REG_SEG_ES << endl; cerr << "REG_SEG_FS" << REG_SEG_FS << endl; cerr << "REG_SEG_GS" << REG_SEG_GS << endl; cerr << "REG_SEG_LAST" << REG_SEG_LAST << endl; cerr << "REG_EFLAGS" << REG_EFLAGS << endl; cerr << "REG_GFLAGS" << REG_GFLAGS << endl; cerr << "REG_EIP" << REG_EIP << endl; cerr << "REG_INST_PTR" << REG_INST_PTR << endl; cerr << "REG_AL" << REG_AL << endl; cerr << "REG_AH" << REG_AH << endl; cerr << "REG_AX" << REG_AX << endl; cerr << "REG_CL" << REG_CL << endl; cerr << "REG_CH" << REG_CH << endl; cerr << "REG_CX" << REG_CX << endl; cerr << "REG_DL" << REG_DL << endl; cerr << "REG_DH" << REG_DH << endl; cerr << "REG_DX" << REG_DX << endl; cerr << "REG_BL" << REG_BL << endl; cerr << "REG_BH" << REG_BH << endl; cerr << "REG_BX" << REG_BX << endl; cerr << "REG_BP" << REG_BP << endl; cerr << "REG_SI" << REG_SI << endl; cerr << "REG_DI" << REG_DI << endl; cerr << "REG_SP" << REG_SP << endl; cerr << "REG_FLAGS" << REG_FLAGS << endl; cerr << "REG_IP" << REG_IP << endl; cerr << "REG_MM_BASE" << REG_MM_BASE << endl; cerr << "REG_MM0" << REG_MM0 << endl; cerr << "REG_MM1" << REG_MM1 << endl; cerr << "REG_MM2" << REG_MM2 << endl; cerr << "REG_MM3" << REG_MM3 << endl; cerr << "REG_MM4" << REG_MM4 << endl; cerr << "REG_MM5" << REG_MM5 << endl; cerr << "REG_MM6" << REG_MM6 << endl; cerr << "REG_MM7" << REG_MM7 << endl; cerr << "REG_MM_LAST" << REG_MM_LAST << endl; cerr << "REG_EMM_BASE" << REG_EMM_BASE << endl; cerr << "REG_EMM0" << REG_EMM0 << endl; cerr << "REG_EMM1" << REG_EMM1 << endl; cerr << "REG_EMM2" << REG_EMM2 << endl; cerr << "REG_EMM3" << REG_EMM3 << endl; cerr << "REG_EMM4" << REG_EMM4 << endl; cerr << "REG_EMM5" << REG_EMM5 << endl; cerr << "REG_EMM6" << REG_EMM6 << endl; cerr << "REG_EMM7" << REG_EMM7 << endl; cerr << "REG_EMM_LAST" << REG_EMM_LAST << endl; cerr << "REG_MXT" << REG_MXT << endl; cerr << "REG_XMM_BASE" << REG_XMM_BASE << endl; cerr << "REG_FIRST_FP_REG" << REG_FIRST_FP_REG << endl; cerr << "REG_XMM0" << REG_XMM0 << endl; cerr << "REG_XMM1" << REG_XMM1 << endl; cerr << "REG_XMM2" << REG_XMM2 << endl; cerr << "REG_XMM3" << REG_XMM3 << endl; cerr << "REG_XMM4" << REG_XMM4 << endl; cerr << "REG_XMM5" << REG_XMM5 << endl; cerr << "REG_XMM6" << REG_XMM6 << endl; cerr << "REG_XMM7" << REG_XMM7 << endl; #if defined(TARGET_IA32E) cerr << "REG_XMM8" << REG_XMM8 << endl; cerr << "REG_XMM9" << REG_XMM9 << endl; cerr << "REG_XMM10" << REG_XMM10 << endl; cerr << "REG_XMM11" << REG_XMM11 << endl; cerr << "REG_XMM12" << REG_XMM12 << endl; cerr << "REG_XMM13" << REG_XMM13 << endl; cerr << "REG_XMM14" << REG_XMM14 << endl; cerr << "REG_XMM15" << REG_XMM15 << endl; cerr << "REG_XMM_LAST" << REG_XMM_LAST << endl; cerr << "REG_YMM_BASE" << REG_YMM_BASE << endl; cerr << "REG_YMM0" << REG_YMM0 << endl; cerr << "REG_YMM1" << REG_YMM1 << endl; cerr << "REG_YMM2" << REG_YMM2 << endl; cerr << "REG_YMM3" << REG_YMM3 << endl; cerr << "REG_YMM4" << REG_YMM4 << endl; cerr << "REG_YMM5" << REG_YMM5 << endl; cerr << "REG_YMM6" << REG_YMM6 << endl; cerr << "REG_YMM7" << REG_YMM7 << endl; cerr << "REG_YMM8" << REG_YMM8 << endl; cerr << "REG_YMM9" << REG_YMM9 << endl; cerr << "REG_YMM10" << REG_YMM10 << endl; cerr << "REG_YMM11" << REG_YMM11 << endl; cerr << "REG_YMM12" << REG_YMM12 << endl; cerr << "REG_YMM13" << REG_YMM13 << endl; cerr << "REG_YMM14" << REG_YMM14 << endl; cerr << "REG_YMM15" << REG_YMM15 << endl; cerr << "REG_YMM_LAST" << REG_YMM_LAST << endl; #endif cerr << "REG_MXCSR" << REG_MXCSR << endl; cerr << "REG_MXCSRMASK" << REG_MXCSRMASK << endl; // cerr << "REG_ORIG_EAX" << REG_ORIG_EAX << endl; cerr << "REG_ORIG_GAX" << REG_ORIG_GAX << endl; cerr << "REG_DR_BASE" << REG_DR_BASE << endl; cerr << "REG_DR0" << REG_DR0 << endl; cerr << "REG_DR1" << REG_DR1 << endl; cerr << "REG_DR2" << REG_DR2 << endl; cerr << "REG_DR3" << REG_DR3 << endl; cerr << "REG_DR4" << REG_DR4 << endl; cerr << "REG_DR5" << REG_DR5 << endl; cerr << "REG_DR6" << REG_DR6 << endl; cerr << "REG_DR7" << REG_DR7 << endl; cerr << "REG_DR_LAST" << REG_DR_LAST << endl; cerr << "REG_CR_BASE" << REG_CR_BASE << endl; cerr << "REG_CR0" << REG_CR0 << endl; cerr << "REG_CR1" << REG_CR1 << endl; cerr << "REG_CR2" << REG_CR2 << endl; cerr << "REG_CR3" << REG_CR3 << endl; cerr << "REG_CR4" << REG_CR4 << endl; cerr << "REG_CR_LAST" << REG_CR_LAST << endl; cerr << "REG_TSSR" << REG_TSSR << endl; cerr << "REG_LDTR" << REG_LDTR << endl; cerr << "REG_TR_BASE" << REG_TR_BASE << endl; cerr << "REG_TR3" << REG_TR3 << endl; cerr << "REG_TR4" << REG_TR4 << endl; cerr << "REG_TR5" << REG_TR5 << endl; cerr << "REG_TR6" << REG_TR6 << endl; cerr << "REG_TR7" << REG_TR7 << endl; cerr << "REG_TR_LAST" << REG_TR_LAST << endl; cerr << "REG_FPST_BASE" << REG_FPST_BASE << endl; cerr << "REG_FPSTATUS_BASE" << REG_FPSTATUS_BASE << endl; cerr << "REG_FPCW" << REG_FPCW << endl; cerr << "REG_FPSW" << REG_FPSW << endl; cerr << "REG_FPTAG" << REG_FPTAG << endl; cerr << "REG_FPIP_OFF" << REG_FPIP_OFF << endl; cerr << "REG_FPIP_SEL" << REG_FPIP_SEL << endl; cerr << "REG_FPOPCODE" << REG_FPOPCODE << endl; cerr << "REG_FPDP_OFF" << REG_FPDP_OFF << endl; cerr << "REG_FPDP_SEL" << REG_FPDP_SEL << endl; cerr << "REG_FPSTATUS_LAST" << REG_FPSTATUS_LAST << endl; cerr << "REG_FPTAG_FULL" << REG_FPTAG_FULL << endl; cerr << "REG_ST_BASE" << REG_ST_BASE << endl; cerr << "REG_ST0" << REG_ST0 << endl; cerr << "REG_ST1" << REG_ST1 << endl; cerr << "REG_ST2" << REG_ST2 << endl; cerr << "REG_ST3" << REG_ST3 << endl; cerr << "REG_ST4" << REG_ST4 << endl; cerr << "REG_ST5" << REG_ST5 << endl; cerr << "REG_ST6" << REG_ST6 << endl; cerr << "REG_ST7" << REG_ST7 << endl; cerr << "REG_ST_LAST" << REG_ST_LAST << endl; cerr << "REG_FPST_LAST" << REG_FPST_LAST << endl; cerr << "REG_SEG_FS_BASE" << REG_SEG_FS_BASE << endl; cerr << "REG_SEG_GS_BASE" << REG_SEG_GS_BASE << endl; cerr << "REG_INST_BASE" << REG_INST_BASE << endl; cerr << "REG_INST_SCRATCH_BASE" << REG_INST_SCRATCH_BASE << endl; cerr << "REG_INST_G0" << REG_INST_G0 << endl; cerr << "REG_INST_G1" << REG_INST_G1 << endl; cerr << "REG_INST_G2" << REG_INST_G2 << endl; cerr << "REG_INST_G3" << REG_INST_G3 << endl; cerr << "REG_INST_G4" << REG_INST_G4 << endl; cerr << "REG_INST_G5" << REG_INST_G5 << endl; cerr << "REG_INST_G6" << REG_INST_G6 << endl; cerr << "REG_INST_G7" << REG_INST_G7 << endl; cerr << "REG_INST_G8" << REG_INST_G8 << endl; cerr << "REG_INST_G9" << REG_INST_G9 << endl; cerr << "REG_INST_G10" << REG_INST_G10 << endl; cerr << "REG_INST_G11" << REG_INST_G11 << endl; cerr << "REG_INST_G12" << REG_INST_G12 << endl; cerr << "REG_INST_G13" << REG_INST_G13 << endl; cerr << "REG_INST_G14" << REG_INST_G14 << endl; cerr << "REG_INST_G15" << REG_INST_G15 << endl; cerr << "REG_INST_G16" << REG_INST_G16 << endl; cerr << "REG_INST_G17" << REG_INST_G17 << endl; cerr << "REG_INST_G18" << REG_INST_G18 << endl; cerr << "REG_INST_G19" << REG_INST_G19 << endl; cerr << "REG_INST_TOOL_LAST" << REG_INST_TOOL_LAST << endl; cerr << "REG_BUF_BASE0" << REG_BUF_BASE0 << endl; cerr << "REG_BUF_BASE1" << REG_BUF_BASE1 << endl; cerr << "REG_BUF_BASE2" << REG_BUF_BASE2 << endl; cerr << "REG_BUF_BASE3" << REG_BUF_BASE3 << endl; cerr << "REG_BUF_BASE4" << REG_BUF_BASE4 << endl; cerr << "REG_BUF_BASE5" << REG_BUF_BASE5 << endl; cerr << "REG_BUF_BASE6" << REG_BUF_BASE6 << endl; cerr << "REG_BUF_BASE7" << REG_BUF_BASE7 << endl; cerr << "REG_BUF_BASE8" << REG_BUF_BASE8 << endl; cerr << "REG_BUF_BASE9" << REG_BUF_BASE9 << endl; cerr << "REG_BUF_LAST" << REG_BUF_LAST << endl; cerr << "REG_BUF_END0" << REG_BUF_END0 << endl; cerr << "REG_BUF_END1" << REG_BUF_END1 << endl; cerr << "REG_BUF_END2" << REG_BUF_END2 << endl; cerr << "REG_BUF_END3" << REG_BUF_END3 << endl; cerr << "REG_BUF_END4" << REG_BUF_END4 << endl; cerr << "REG_BUF_END5" << REG_BUF_END5 << endl; cerr << "REG_BUF_END6" << REG_BUF_END6 << endl; cerr << "REG_BUF_END7" << REG_BUF_END7 << endl; cerr << "REG_BUF_END8" << REG_BUF_END8 << endl; cerr << "REG_BUF_END9" << REG_BUF_END9 << endl; cerr << "REG_BUF_ENDLAST" << REG_BUF_ENDLAST << endl; cerr << "REG_INST_SCRATCH_LAST" << REG_INST_SCRATCH_LAST << endl; cerr << "REG_LAST" << REG_LAST << endl; }
Pilp5/options.hh
:
#ifndef OPTIONS_HH #define OPTIONS_HH #include <string> #include <vector> #include <map> #include <stdint.h> using std::string; using std::vector; using std::map; class Options { public: Options(); void Read(); void ReadXML(); map<string, string> option_list; }; extern Options options; #endif // OPTIONS_HH
Pilp5/options.cpp
:
#include "options.hh" #include <iostream> #include <fstream> #include <iomanip> #include <cstdlib> #include <map> #include <libxml++/libxml++.h> #include <libxml++/parsers/textreader.h> using std::ifstream; using std::cerr; using std::endl; using std::map; using std::setw; Options::Options() { option_list["command"] = "None"; option_list["resdir"] = "None"; option_list["length"] = "None"; option_list["depth"] = "0"; option_list["inst_control"] = "None"; option_list["dump_control"] = "None"; option_list["floatonly"] = "None"; } void Options::ReadXML() { // Set the global C and C++ locale to the user-configured locale, // so we can use std::cout with UTF-8, via Glib::ustring, without exceptions. std::locale::global(std::locale("")); #ifdef LIBXMLCPP_EXCEPTIONS_ENABLED try { #endif //LIBXMLCPP_EXCEPTIONS_ENABLED cerr << "---------------------------------------------------------------------------------------------------------" << endl; cerr << "Reading command file : ..." << endl; cerr << "---------------------------------------------------------------------------------------------------------" << endl; // cerr << " --- XML DEBUG 1 ---" << endl; xmlpp::TextReader reader("_ilptool_command.xml"); // cerr << " --- XML DEBUG 2 ---" << endl; reader.read(); reader.read(); string current_option=""; while(reader.read()) { switch(reader.get_node_type()) { case (xmlpp::TextReader::Element): // std::cerr << "ELEMENT: " << reader.get_name() << std::endl; current_option = reader.get_name(); if (option_list.find(current_option) != option_list.end()) { // std::cerr << "Set current option to : " << current_option << " ..." << std::endl; // current_option = } else { std::cerr << "Invalid option : " << current_option << "" << std::endl; current_option=""; } break; case (xmlpp::TextReader::Text): // std::cerr << "TEXT : " << reader.get_name() << std::endl; if(reader.has_value()) { // std::cout << "value: '" << reader.get_value() << "'" << std::endl; if (option_list.find(current_option) != option_list.end()) option_list[current_option] = reader.get_value(); } else // std::cout << "novalue" << std::endl; default: break; } } #ifdef LIBXMLCPP_EXCEPTIONS_ENABLED } catch(const std::exception& e) { std::cout << "Exception caught: " << e.what() << std::endl; } #endif //LIBXMLCPP_EXCEPTIONS_ENABLED cerr << "Option list :" << endl; for (map<string, string>::iterator it=option_list.begin(); it!=option_list.end(); it++) { string cmd = "[" + it->first + "]"; // cerr << "\t"<< setw(8) << "[" << it->first << "]" << setw(8) << " = " << it->second << endl; cerr << setw(25) << cmd.c_str() << setw(0) << "" << " = " << it->second << endl; } cerr << "---------------------------------------------------------------------------------------------------------" << endl; }
Pilp5/utils/memory.hh
:
/* * Copyright (c) 2007, * Commissariat a l'Energie Atomique (CEA) * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * - Neither the name of CEA nor the names of its contributors may be used to * endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Gilles Mouchard (gilles.mouchard@cea.fr) * Daniel Gracia Perez (daniel.gracia-perez@cea.fr) */ #ifndef MEMORY_HH #define MEMORY_HH #include <inttypes.h> #include "hash_table.hh" /* forward declaration */ template <class PHYSICAL_ADDR, uint32_t PAGE_SIZE> class Memory; template <class PHYSICAL_ADDR, uint32_t PAGE_SIZE = 1024 * 1024> class MemoryPage { public: MemoryPage(PHYSICAL_ADDR _key); ~MemoryPage(); private: friend class HashTable<PHYSICAL_ADDR, MemoryPage<PHYSICAL_ADDR, PAGE_SIZE> >; friend class Memory<PHYSICAL_ADDR, PAGE_SIZE>; PHYSICAL_ADDR key; MemoryPage<PHYSICAL_ADDR, PAGE_SIZE> *next; // uint8_t *storage; uint32_t *storage; }; template <class PHYSICAL_ADDR, uint32_t PAGE_SIZE = 1024 * 1024> class Memory { public: Memory(); //, PHYSICAL_ADDR org, uint64_t bytesize); virtual ~Memory(); /* unisim::service::interfaces::Memory methods */ virtual void Reset(); /* virtual bool WriteMemory(PHYSICAL_ADDR physical_addr, const void *buffer, uint32_t size); virtual bool ReadMemory(PHYSICAL_ADDR physical_addr, void *buffer, uint32_t size); bool WriteMemory(PHYSICAL_ADDR physical_addr, const void *buffer, uint32_t size, const uint8_t *byte_enable, uint32_t byte_enable_length, uint32_t streaming_width); bool ReadMemory(PHYSICAL_ADDR physical_addr, void *buffer, uint32_t size, const uint8_t *byte_enable, uint32_t byte_enable_length, uint32_t streaming_width); void *GetDirectAccess(PHYSICAL_ADDR physical_addr, PHYSICAL_ADDR& physical_start_addr, PHYSICAL_ADDR& physical_end_addr); */ uint32_t ReadMemory(PHYSICAL_ADDR physical_addr, uint32_t size); void WriteMemory(uint32_t cycle, PHYSICAL_ADDR physical_addr, uint32_t size); protected: PHYSICAL_ADDR org; // uint32_t bytesize; PHYSICAL_ADDR bytesize; PHYSICAL_ADDR lo_addr; PHYSICAL_ADDR hi_addr; private: HashTable<PHYSICAL_ADDR, MemoryPage<PHYSICAL_ADDR, PAGE_SIZE> > hash_table; // Parameter<PHYSICAL_ADDR> param_org; // Parameter<uint32_t> param_bytesize; }; #endif // MEMORY_HH
Pilp5/utils/memory.tcc
:
/* * Copyright (c) 2007, * Commissariat a l'Energie Atomique (CEA) * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * - Neither the name of CEA nor the names of its contributors may be used to * endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Gilles Mouchard (gilles.mouchard@cea.fr) * Daniel Gracia Perez */ #ifndef MEMORY_TCC #define MEMORY_TCC #include <iostream> #include <inttypes.h> #include "hash_table.hh" #include <cstring> #include <cstdlib> using std::cerr; using std::endl; template <class PHYSICAL_ADDR, uint32_t PAGE_SIZE> MemoryPage<PHYSICAL_ADDR, PAGE_SIZE>::MemoryPage(PHYSICAL_ADDR _key) : key(_key), next(0) { // storage = new uint8_t[PAGE_SIZE]; storage = new uint32_t[PAGE_SIZE]; memset(storage, 0, PAGE_SIZE); } template <class PHYSICAL_ADDR, uint32_t PAGE_SIZE> MemoryPage<PHYSICAL_ADDR, PAGE_SIZE>::~MemoryPage() { delete[] storage; } template <class PHYSICAL_ADDR, uint32_t PAGE_SIZE> Memory<PHYSICAL_ADDR, PAGE_SIZE>::Memory() : // Object(name, parent), org(0), // bytesize((uint32_t)-1), bytesize((PHYSICAL_ADDR)-1), //bytesize((PHYSICAL_ADDR)0xffffffff), lo_addr(org), hi_addr(org + (bytesize - 1)) { Reset(); /* cerr << "org : " << hex << org << dec << endl; cerr << "bytesize: " << hex << bytesize << dec << endl; cerr << "lo_addr : " << hex << lo_addr << dec << endl; cerr << "hi_addr : " << hex << hi_addr << dec << endl; */ } template <class PHYSICAL_ADDR, uint32_t PAGE_SIZE> Memory<PHYSICAL_ADDR, PAGE_SIZE>::~Memory() { } /* template <class PHYSICAL_ADDR, uint32_t PAGE_SIZE> void Memory<PHYSICAL_ADDR, PAGE_SIZE>::OnDisconnect() { } template <class PHYSICAL_ADDR, uint32_t PAGE_SIZE> bool Memory<PHYSICAL_ADDR, PAGE_SIZE>::Setup() { lo_addr = org; hi_addr = org + (bytesize - 1); return true; } */ template <class PHYSICAL_ADDR, uint32_t PAGE_SIZE> void Memory<PHYSICAL_ADDR, PAGE_SIZE>::Reset() { hash_table.Reset(); } template <class PHYSICAL_ADDR, uint32_t PAGE_SIZE> //bool Memory<PHYSICAL_ADDR, PAGE_SIZE>::WriteMemory(PHYSICAL_ADDR physical_addr, const void *buffer, uint32_t size) void Memory<PHYSICAL_ADDR, PAGE_SIZE>::WriteMemory(uint32_t cycle, PHYSICAL_ADDR physical_addr, uint32_t size) { uint32_t copied; PHYSICAL_ADDR addr; if(physical_addr < lo_addr || (physical_addr + (size - 1)) > hi_addr || (physical_addr + size) < physical_addr) {//return false; cerr << "Write Memory access error !!!" << endl; cerr << "org : " << hex << org << dec << endl; cerr << "bytesize: " << hex << bytesize << dec << endl; cerr << "lo_addr : " << hex << lo_addr << dec << endl; cerr << "hi_addr : " << hex << hi_addr << dec << endl; cerr << "addr : " << hex << physical_addr << dec << endl; abort(); } // the third condition is for testing overwrapping (gdb did it !) PHYSICAL_ADDR key; MemoryPage<PHYSICAL_ADDR, PAGE_SIZE> *page; copied = 0; addr = physical_addr - lo_addr; do { uint32_t copy_size; uint32_t max_copy_size; key = (addr + copied) / PAGE_SIZE; page = hash_table.Find(key); if(!page) { page = new MemoryPage<PHYSICAL_ADDR, PAGE_SIZE>(key); hash_table.Insert(page); } max_copy_size = PAGE_SIZE - ((addr + copied) & (PAGE_SIZE - 1)); if(size - copied > max_copy_size) copy_size = max_copy_size; else copy_size = size - copied; //memcpy(&page->storage[(addr + copied) & (PAGE_SIZE - 1)], // &((uint8_t *)buffer)[copied], // copy_size); /* memset(&page->storage[(addr + copied) & (PAGE_SIZE - 1)], cycle, copy_size); */ for (uint32_t i=0; i<copy_size; i++) { page->storage[(addr + copied + i) & (PAGE_SIZE - 1)] = cycle; } copied += copy_size; } while(copied != size); //return true; } template <class PHYSICAL_ADDR, uint32_t PAGE_SIZE> //bool Memory<PHYSICAL_ADDR, PAGE_SIZE>::ReadMemory(PHYSICAL_ADDR physical_addr, void *buffer, uint32_t size) uint32_t Memory<PHYSICAL_ADDR, PAGE_SIZE>::ReadMemory(PHYSICAL_ADDR physical_addr, uint32_t size) { uint32_t copied; uint32_t cycle_max=0; PHYSICAL_ADDR addr; if(physical_addr < lo_addr || (physical_addr + (size - 1)) > hi_addr || (physical_addr + size) < physical_addr) {//return false; cerr << "Read Memory access error !!!" << endl; cerr << "org : " << hex << org << dec << endl; cerr << "bytesize: " << hex << bytesize << dec << endl; cerr << "lo_addr : " << hex << lo_addr << dec << endl; cerr << "hi_addr : " << hex << hi_addr << dec << endl; cerr << hex << physical_addr << dec << endl; abort(); } // the third condition is for testing overwrapping (gdb did it !) PHYSICAL_ADDR key = physical_addr / PAGE_SIZE; MemoryPage<PHYSICAL_ADDR, PAGE_SIZE> *page; copied = 0; addr = physical_addr - lo_addr; do { uint32_t copy_size; uint32_t max_copy_size; key = (addr + copied) / PAGE_SIZE; page = hash_table.Find(key); if(!page) { page = new MemoryPage<PHYSICAL_ADDR, PAGE_SIZE>(key); hash_table.Insert(page); } max_copy_size = PAGE_SIZE - ((addr + copied) & (PAGE_SIZE - 1)); if(size - copied > max_copy_size) copy_size = max_copy_size; else copy_size = size - copied; //memcpy(&((uint8_t *)buffer)[copied], // &page->storage[(addr + copied) & (PAGE_SIZE - 1)], // copy_size); for (uint32_t i=0; i<copy_size; i++) { // cmax=((c=lookforcycle(amr+i))>cmax)?c:cmax; uint32_t ccycle = page->storage[(addr + copied + i) & (PAGE_SIZE - 1)]; cycle_max = (ccycle>cycle_max)?ccycle:cycle_max; } copied += copy_size; } while(copied != size); return cycle_max; } /* template <class PHYSICAL_ADDR, uint32_t PAGE_SIZE> bool Memory<PHYSICAL_ADDR, PAGE_SIZE>::WriteMemory(PHYSICAL_ADDR physical_addr, const void *buffer, uint32_t size, const uint8_t *byte_enable, uint32_t byte_enable_length, uint32_t streaming_width) { uint32_t offset; PHYSICAL_ADDR addr; uint32_t byte_enable_offset; uint32_t copied; if(physical_addr < lo_addr || (physical_addr + (size - 1)) > hi_addr || (physical_addr + size) < physical_addr) return false; // the third condition is for testing overwrapping (gdb did it !) PHYSICAL_ADDR key; MemoryPage<PHYSICAL_ADDR, PAGE_SIZE> *page; byte_enable_offset = 0; copied = 0; offset = 0; if(streaming_width == 0) streaming_width = size; addr = physical_addr - lo_addr; do { uint32_t copy_size; uint32_t max_page_copy_size; key = (addr + offset) / PAGE_SIZE; page = hash_table.Find(key); if(!page) { page = new MemoryPage<PHYSICAL_ADDR, PAGE_SIZE>(key); hash_table.Insert(page); } max_page_copy_size = PAGE_SIZE - ((addr + offset) & (PAGE_SIZE - 1)); do { // Compute how many bytes remain in the buffer copy_size = size - offset; // Saturate the amount of bytes with the maximum allowed for the page if(copy_size > max_page_copy_size) copy_size = max_page_copy_size; // Compute how many bytes remain until the end of the streaming window uint32_t max_streaming_copy_size = streaming_width - offset; // Saturate the amount of bytes with the maximum allowed for the streaming window if(copy_size > max_streaming_copy_size) copy_size = max_streaming_copy_size; // Compute the offset from the beginning of the page uint32_t page_offset = (addr + offset) & (PAGE_SIZE - 1); if(byte_enable_length) { uint8_t *src = &((uint8_t *)buffer)[copied]; uint8_t *dst = &page->storage[page_offset]; do { uint8_t mask = byte_enable[byte_enable_offset]; // Combine the buffer and the page content according to the byte enable buffer *dst = ((*dst) & ~mask) | ((*src) & mask); // cycle through the byte enable buffer if(++byte_enable_offset >= byte_enable_length) byte_enable_offset = 0; } while(++src, ++dst, --copy_size); } else { memcpy(&((uint8_t *)buffer)[copied], &page->storage[page_offset], copy_size); } offset += copy_size; copied += copy_size; max_page_copy_size -= copy_size; // Check if the end of the streaming window has been reached if(offset == streaming_width) { // Restart from the initial address offset = 0; if(addr / PAGE_SIZE != key) { // Force another page lookup break; } } } while(copied != size && max_page_copy_size); // Loop until some bytes remain } while(copied != size); return true; } */ /* template <class PHYSICAL_ADDR, uint32_t PAGE_SIZE> bool Memory<PHYSICAL_ADDR, PAGE_SIZE>::ReadMemory(PHYSICAL_ADDR physical_addr, void *buffer, uint32_t size, const uint8_t *byte_enable, uint32_t byte_enable_length, uint32_t streaming_width) { uint32_t offset; PHYSICAL_ADDR addr; uint32_t byte_enable_offset; uint32_t copied; if(physical_addr < lo_addr || (physical_addr + (size - 1)) > hi_addr || (physical_addr + size) < physical_addr) return false; // the third condition is for testing overwrapping (gdb did it !) PHYSICAL_ADDR key; MemoryPage<PHYSICAL_ADDR, PAGE_SIZE> *page; byte_enable_offset = 0; copied = 0; offset = 0; if(streaming_width == 0) streaming_width = size; addr = physical_addr - lo_addr; do { uint32_t copy_size; uint32_t max_page_copy_size; key = (addr + offset) / PAGE_SIZE; page = hash_table.Find(key); if(!page) { page = new MemoryPage<PHYSICAL_ADDR, PAGE_SIZE>(key); hash_table.Insert(page); } max_page_copy_size = PAGE_SIZE - ((addr + offset) & (PAGE_SIZE - 1)); do { // Compute how many bytes remain in the buffer copy_size = size - offset; // Saturate the amount of bytes with the maximum allowed for the page if(copy_size > max_page_copy_size) copy_size = max_page_copy_size; // Compute how many bytes remain until the end of the streaming window uint32_t max_streaming_copy_size = streaming_width - offset; // Saturate the amount of bytes with the maximum allowed for the streaming window if(copy_size > max_streaming_copy_size) copy_size = max_streaming_copy_size; // Compute the offset from the beginning of the page uint32_t page_offset = (addr + offset) & (PAGE_SIZE - 1); if(byte_enable_length) { uint8_t *src = &page->storage[page_offset]; uint8_t *dst = &((uint8_t *)buffer)[copied]; do { uint8_t mask = byte_enable[byte_enable_offset]; // Combine the buffer and the page content according to the byte enable buffer *dst = ((*dst) & ~mask) | ((*src) & mask); // cycle through the byte enable buffer if(++byte_enable_offset >= byte_enable_length) byte_enable_offset = 0; } while(++src, ++dst, --copy_size); } else { memcpy(&page->storage[page_offset], &((uint8_t *)buffer)[copied], copy_size); } offset += copy_size; copied += copy_size; max_page_copy_size -= copy_size; // Check if the end of the streaming window has been reached if(offset == streaming_width) { // Restart from the initial address offset = 0; if(addr / PAGE_SIZE != key) { // Force another page lookup break; } } } while(copied != size && max_page_copy_size); // Loop until some bytes remain } while(copied != size); return true; } */ /* template <class PHYSICAL_ADDR, uint32_t PAGE_SIZE> void *Memory<PHYSICAL_ADDR, PAGE_SIZE>::GetDirectAccess(PHYSICAL_ADDR physical_addr, PHYSICAL_ADDR& physical_start_addr, PHYSICAL_ADDR& physical_end_addr) { PHYSICAL_ADDR addr; if(physical_addr < lo_addr || physical_addr > hi_addr) return 0; PHYSICAL_ADDR key; MemoryPage<PHYSICAL_ADDR, PAGE_SIZE> *page; addr = physical_addr - lo_addr; key = addr / PAGE_SIZE; page = hash_table.Find(key); if(!page) { page = new MemoryPage<PHYSICAL_ADDR, PAGE_SIZE>(key); hash_table.Insert(page); } physical_start_addr = key * PAGE_SIZE; physical_end_addr = physical_start_addr + PAGE_SIZE - 1; return page->storage; } } // end of namespace ram } // end of namespace memory } // end of namespace cxx } // end of namespace component } // end of namespace unisim */ #endif // MEMORY_TCC