 So, in this tutorial we will see what instrumentation and what dynamic binary instrumentation is. Then we would basically see how to how pin actually does dynamic binary instrumentation and how to use pin for architectural study. So, I am going to be using pin for your homework assignment. So, please pay attention and if you have any questions please feel free to interrupt So, let us start with instrumentation. So, instrumentation is a technique for inserting extra code into an application to observe study and even change its behavior. Lot of program analysis to use instrumentation for performance profiling, error detection and capture and read data. Valgrind uses instrumentation for memory error analysis. It can detect misuse of malloc and free. So, by misuse of malloc I mean that you have allocated some memory segment using malloc and you are not seeing when it is used in. So, it leads to memory. So, Valgrind can identify those. By misuse of free I mean that you are paying some unallocated memory segment. So, it will lead to segmentation point. It can even detect unallocated variables and dangling pointers. Do you guys know what dangling pointers are? Dangling pointers actually point to a memory region which has not been allocated by the application. So, dereferencing them may lead to segmentation points. Intel's inspector also uses instrumentation for thread error analysis. It can detect data races in your multi-thread application and even deadlocks in multi-threaded application. Intel's vtune amplifier also uses instrumentation for performance analysis. It can locate hotspots in your application. And it can even do lock weight analysis. It can give you the lock contention time. We would be mainly using instrumentation for architectural study. We would be doing processor, branch predictor and cache simulation using instrumentation tools. And you will be using instrumentation to collect instruction cases. And these instruction cases would then be spread to some other place based simulator, details simulator. So, Intel's software development simulator also uses instrumentation to emulate new x86 instruction. Suppose that you want to implement some new x86 instruction and study what benefit you would get because of it. So, what you do is that you register with software development emulator, a function which implements the functional behavior of the application. And when software development emulator encounters this new instruction, instead of trying to execute it immediately, it will actually call the function that you have to emulate its behavior. So, now moving on to instrumentation approaches. So, when we are doing instrumentation, the two main questions that arise are where do we want to insert code and what code do we want to insert? So, these two questions are mostly related to the problem that we are trying to solve. So, if you are doing cache simulation then on execution of each load store instruction, you would want to look up a cache model that you have developed. So, we are, so in cache simulation, so we are inserting code at execution of a load store instruction and the code that we are inserting is to look up a cache model. Similarly, in the branch predictor performance study, you would want to insert code just before the execution of a branch instruction and it would look up the branch predictor that we have prepared and tell us whether there is a branch miss or ahead. The next question that arises is how do we actually go about inserting this code? There are various approaches to it. We can directly modify the application source code and you directly write code, add code in it. This is called source code instrumentation. It is not, you must have used it for measuring some time taken by a particular chunk of application. You add code before that chunk to measure the starting time and then at the end of it to measure the end time to get the time that is consumed at a particular chunk. It is not widely used. We could have suffered some major drawbacks. You, because you are doing source code instrumentation, you should have the source code with you. Just modifying, just instrumenting the source code of the application is not sufficient. You would even want to modify the source code of the third party libraries that is used. Why would we want to modify the third party libraries that the application is using? Think about cache simulation. You are trying to add, insert code just before each load store instruction to look up the cache model. Your library functions that you are using may be executing some load store instruction. You would want to insert code to look up the cache model before them also. Just instrumenting the application source code is not sufficient. You would have to instrument all the libraries that it is using. This finally requires recompilation and re-linking the application. The second technique is to do static binary. Just one minute. So can you think of, like one, so he has talked about the drawback, right? Source everything. Why is it a problem? Does it occur to you that it's a problem? Source everything. And it's a why. Most of the commercial applications, you don't have the source code. Right, so if you have the source code of Microsoft Word, how many has that? How many has that? There will be two in Microsoft Word, why not? This will be right. Most commonly used applications are some of these commercial applications. You don't have the source code for them. So it's difficult to instrument them through source code instrumentation. The second technique is static binary instrumentation. Here it is similar to source code instrumentation, but instead of modifying the source code, here we directly modify the executable binary file of the application. It's similar to similar drawbacks. You need to know what is the binary format and you have to, because you have to modify it. So we are trying to insert some extra code in the binary. So what could happen is that the instruction addresses may change because of this extra code that we added. So now if there's a branch instruction, the branch target, we would even have to change the branch target. So the starting extra code is not in the original, it has also needs to be modified. Then code discovery is another problem which static binary instrumentation suffers from. Code discovery I mean is that most of the applications that we use, these days they use dynamic libraries. So the third party libraries that we use, the code for the third party libraries is not there in the application library. It is loaded when the application is loaded at runtime. So when you're doing static binary instrumentation, you don't have the code for the third party libraries. So here also you would have to actually look for the binaries of these libraries and modify them also. So here also just modifying the application binary is not sufficient. The third approach which is most commonly used instrumentation approach is dynamic binary instrumentation. In dynamic binary instrumentation, you instrument the application at runtime. As the application is executing, you insert some extra code in it and you execute it along with the application. It is similar to just in time compilation. So are you guys familiar with just in time compilation? Do you know any compiler which... Java. ...gview. ...gview. How it works? It changes code into binary code. And after that, whenever... It changes what? ...in binary code. It changes to binary code and then that binary code is compiled at that wherever you want. No. So that's not just in time. That's just Java compilation. So Java... So when you compile a Java program, it generates byte code in it. So the class files contain byte code. Now when you run this Java program with the Java virtual machine, you write Java and the class name. So when you run it... So Java is the Java virtual machine. So when it starts executing the program, it reads the byte code from the class files and it generates machine code for it, corresponding to it. And then the generated machine code is actually what is executed. So it keeps on reading machine... byte code and generates machine code and then execute it. This process keeps on doing it until the application ends. So dynamic binary instrumentation is similar to the state-time compilation. Except here, instead of translating from byte code to machine code, you are translating from machine code to machine code. And while it is doing this translation from machine code to machine code, you have an opportunity to insert some extra code in the application. So while this translation is going on, it adds extra code and then the generated code is actually... it has the original code and it has the extra code that you have added and then it executes it. Okay? We have to add machine code into machine code. Did I already add machine code into machine code? Yeah. And then finally machine code is what runs. You would see how it works. So the benefit of dynamic binary instrumentation is that you do not need to recompile and reading the application. You can... because everything is happening at runtime, you can directly attach your instrumentation to a running process. So most of the tools that you will instrument are like web servers and database servers, which are daemon processors. So you can directly attach to them. And they all do that. Yeah. Okay. So here the code discovery also becomes much easier because if your application is using some dynamic loaded... dynamically loaded... dynamically loaded libraries, then the libraries code would also be loaded first in the address space. And when it is about to be executed, at that point the instrumentation engine can insert code in it also. So just like in static binary, we have to explicitly go and look for third party libraries and add code. It's not necessary here. And this even takes care of self-modifying applications. So self-modifying applications modify their own source code as they are executing. So that would also be taken care of by this. We would see how this works after some time. Okay. Let's move to PIN. So PIN is a dynamic binary instrumentation engine. It is not free. It is freely available, but it is not open source. You can go to this website PINTOOL.org and download the PIN plate for your OS. You will get a compressed archive. You decompress it. There is nothing to install. As you decompress, you are ready to use it. It works on H8632 bit and 64 bit platforms and all the major operating systems when it was Mac OS. The Mac OS support is relatively new. I don't know how it works. Well, it works. It can instrument unmodified applications like database servers, web servers, web browser. You can run an application on any of these operating systems and you can instrument it. That's it. So PIN, if you actually get a binary PIN a binary of the PIN instrumentation engine. So PIN instrumentation engine exposes a rich set of APIs. Using this API, you can write in C or C++ your own instrumentation tools. And these instrumentation tools are called PIN tools. There are a lot of sample PIN tools provided in with the PIN kit. This is the path name of the this is the directory in which the sample PIN tools are. So as I told previously that PIN is a dynamic binary instrumentation engine. So what it is doing is that it reads the original application code and it is generating some code for this corresponding to this application code. While it is doing this, it uses the information from the PIN tool to modify this generation process and what it will do, it will insert some extra code which PIN tool will tell. This is where it wants to insert extra code and what code it has to insert and PIN would actually do that for the PIN tool. So PIN uses PIN tools to instrument applications at real time during the dynamic binary combination and PIN tools can be thought of as plugins which modify the code generation process of PIN. So are you clear about the this tool is just in time just in time compiler just in time compiler. It is similar to a just in time compiler. Just in time compiler you are generating machine code corresponding to some byte code. Here you are generating machine code corresponding to this. This will also generate the time process for executing. Yeah, it will do all these things at one time. When the application is executing, at that point it will be executing the application and at the same point it will be adding some extra code in the application and adding some extra code also. So PIN tool consists of instrumentation and analysis routines. These are simple functions instrumentation routines are actually instrumentation routines are called by PIN whenever new code has to be generated. Whenever PIN is about to generate some new code it will call these instrumentation routines. So when an instrumentation routine actually investigates the static properties of the original code and decides if and where to inject calls to analysis routine. So what it is doing it looks through the code and it decides whether I want to inject some code over here and it will inject calls to analysis routines. Both of these are contained in the PIN tool. And so once it has decided that it has to insert some call to analysis it will ask PIN to insert that call. So once the code is generated it is stored in a cache and it will be renewed. So if you have a for loop which has some number of iterations so the first time when the first iteration is being executed at that point PIN will generate the code for the first iteration and while it is generating code for the first iteration it will instrument it also. So when this first iteration has been executed for the second iteration it won't again call the instrumentation routine to generate code because it has already cached that code in the code cache. So this using cache to store the generated code is an optimization of the string time compiler to reduce the cost of code generation actually speeds up the process so just to clarify this cache is not a hardware it's a software cache it's a part of memory this is for storing the so as long as the generated code is there in the code cache instrumentation is not required it can directly execute the code and so for some application code which has already been instrumented the generated code is present in the code cache so if that code store this lifetime remains in the code cache the instrumentation routine won't be called again for it so most of the time this code the sign of code cache is sufficient to cache the whole application so instrumentation function would only be called for the original code once so these are called at most once for an application so these are instrumentation and so viewer injecting calls to analysis routine so analysis routine actually define what the instrumentation code would do and so this is the original application code for this the generated because we are translating from machine code to machine code the generated code would also be almost similar to it so instruction would remain same the register allocation might differ and we have inserted a call to analysis so this is the original code we have the pin has generated this code for it and the pin tool has instrumented this code and injected a call to analysis one function so each time this compare instruction is about to be executed just before this compare instruction this analysis function would also be executed so each instruction which has been instrumented the analysis functions would be executed each time that instruction is also executed you get this so the instrumentation routines are telling you what instruction to instrument so you can where to instrument you can put it after instruction before instruction we will talk about that analysis routine is telling you what to do so the where add the where and the what here is injecting call to analysis routines and the where is decided by the instrumentation routine instrumentation means only inserting calls yeah and these instrumentation functions would be called at most of the time once for each instruction and the analysis function would be called each time that instruction is executed so just one more comment so you can see that the instrumentation in the best possible case should be invoked exactly once for each instruction assuming that you instrument every instruction so provided of course we have space encode cache and all these things whereas analysis routine for a particular instruction will get invoked every time that instruction is executed because the code has been so generated code contains a call to this analysis routine so each time it traverses this code path this analysis function would be called so analysis routine would be called each time it traverses this so so pin tool consists of instrumentation analysis routine but so pin tool also registers which instrumentation routine pin has to call so it registers a call back to the instrumentation routine which pin should be used and pin tool so just like it was registering call backs to instrumentation routine pin tool can also register call back for notification event call backs to routines for notification event these notification events can be thread start thread end fork of a child process or these can be the application end or image loading and unloading here image refers to a library which has been binary file which has been loaded so whenever a binary file for a dynamic library is loaded we can call a function we can register a call to a function so these are actually these event notifications are generally used initializing some part of the pin tool so pin tool is a cc++ program you write it you compile it you create a .sofile for a library is this visible so you compile it you get a pin tool .sofile and instrumentation engine is provided with the pin grid so you supply the pin tool to the instrumentation engine as a command line argument and after this double slash you supply the application that you want to instrument the application binary so these pin tools either you can use the pin kit sample tools or you can write your own and you can attach pin to already running process for that you have to supply the PID of the process with the dash PID command line so you are going to get some examples of the PID after this there are already examples so you get this so let's look at a you are trying to write a pin tool which actually counts the number of instructions that have been executed so the code the assembly code here is actually the applications code and what we want to do is that we want to insert these counter plus plus we want to increment the counter when insert code to increment this counter just before each instruction so whenever this instruction is about to be executed just before it the counter would be incremented so in this way you can maintain the number of instructions that are executed so just one question so in that example in most cases we try to incline the analysis function so it was inserting calls to analysis routine so here our analysis routine would consist of incrementing this counter but pin so you compile this pin tool so it also does compiler optimization so up there it will see that it is a simple function so most only it will incline these functions so this is what we want to do suppose that we have written this pin tool and so we want to instrument ls so this is what ls normally prints when we run it with pin like this this is our tool ins count 0.so okay I see so you are running ls in some directory which has these files and when we run it with pin it gives the this is the output from ls and this is what pin tool will output okay so it will it will give us the number of instructions that the ls command is executed does anybody follow this one okay so yeah this is the pin tool and by after double slash this is the binary that we want to instrument so you want to show the pin tool yeah for this so let's see so this is the code for the ins count pin tool it's a simple c++ application and this is the file in the pin kit in the source tool folder we can just take in from this file okay so let's see this source code it has some header files we include the pin.h header file because we are going to use the pin API functions we define this 64 bit integer value this is the counter which is going to keep the count for number of instructions which is executed initialize it to 0 then we have this do count function which increments this counter by 1 whenever it is called then we have this function instruction it take some arguments and this calls this instruction ins insert call function okay this is a pin API function we will talk about the input argument but let's see the third argument the third argument is a pointer to this do count function okay so the third argument is a pointer to the do count function okay now the other function is the phini function we will talk about what are the input arguments are and it just prints on the standard stder the iCount value okay in the main function so this is your pin to encode in the main function we have 4 pin API calls the first one is pin array then is ins add instrument function this takes a pointer to the instruction function so this instruction function is defined over here okay and then there is pin add phini function this takes a pointer to the phini function which is defined in the pin tool so we are using function pointers quite a lot okay and then there is pin start program okay now so pin in it actually takes a command line argument you can pass some command line arguments also to the pin tool so here we are passing the arguments to the pin to initialize the command line arguments and runtime system but can you overwrite the phini function no you cannot right you have to always so your pin tool will all this will be the first function that your pin tool will execute this has to be always present so it's internal cannot explore you cannot you can't modify any of these yeah yeah now I am saying you can here atleast you can pass a function pointer there you don't have any problem yeah so so ins add instrument function is so it takes argument as the so this is our so through ins add instrument function the pin tool is registering with pin what is the instrumentation routine to call when it is about to generate code so this says that whenever pin is about to generate code for an instruction it should first before generating the code it should call the instruction function okay so this is the instruction function instrumentation routine it would be called each time pin is about to generate code so let's see what we are doing in the instrumentation function the instrumentation function takes as the input a reference to the instruction for which pin is about to generate code and the second argument here is the the argument that is passed here okay so this zero is passed in plus you might also want to mention that it's the IAIS prefix I would okay you will be able to so this is registering whenever pin is about to generate code for instruction it should call this instruction function before that and the second argument here is this zero so we not use this much so most of the time it would be zero okay now let's see what we are doing inside the instrumentation instrumentation function here we are calling this INS insert call function here we are so we want to insert call to this we want to increment the counter at each before each instruction okay so we are saying that before this instruction we want to we are asking pin to insert a call to this do count function before before it generates before the code for this instruction okay that's the second argument this is the IAIS mentioned before that's why I am saying so we would talk about this I point before to leave it for now and this IAIS again we will talk about these okay so INS insert call is saying asking pin to inject a call to do count function before it generates code for this INS okay this instruction function can be called anytime no this instruction function is the instrumentation function it will be called by pin whenever pin is about to generate code for an instruction okay so suppose that pin is about to generate code for this compare instruction so before generating code for it pin will call the instruction function the instruction function says that insert a call before before you generate code for this function to insert a call to this do count function okay so call do count then pin will generate code for this instruction okay so this how does it know when to call this function you are saying before doing instrumentation how does it know when to do instrumentation that is I can know but that INS prefix isn't it telling it that you should do this for every instruction I have come to I am saying that INS instrument add function is saying that whenever it is about to generate code for instruction it should call this instruction function first and this instruction function is the instrumentation function it is asking pin to insert a call inject a call to do count function just before it it generates code for this this particular instruction okay you any doubt see can I say this function with this another function yeah yes you can have as many instrumentation functions you can have another instrumentation function which may be inserting call to some other analysis routine okay you can insert call to the second analysis routine here on you you can do another INS insert call some do count to specific function add this call to specific function so you are saying that suppose whenever printed is being called so till now we are not analyzing what this instruction is this instruction may be called to printed we can even analyze that I will come to that so this is just introducing what instrumentation and analysis routines are do you understand just one comment here is that the purpose of phini is to so the do count is the analysis routine okay now let's focus on this pin add phini function okay before that so this is your instrumentation point in the next slide I will talk about instrumentation point and this is your end argument to the insert call so that's a marker yeah that's a marker okay now so I told you previously that printed can also register callbacks to even for instance callbacks to routine for even so pin add phini is registering a callback for phini function whenever the application is about to exist so it registers a callback for application and even whenever the application is about to exist it will call this phini function okay so that's what we want to do whenever the application is about to exist we would print the number of instructions that have executed okay so this function just prints count and the instructions that have executed is it abnormal anyway yeah at that point also this will be gone yeah so you can use this function for any other purpose whatever you want to do at termination so in this case we are just using a count yeah here we were counting number of instructions so we just print the count I mean you may have allocated some exact memory for your print tool you may free it at application end okay so this even functions are generally for initializing and cleanup at the end so here can you see out also or is there a problem yeah you can use see out also not included instrumentation okay so when this function so here we were initializing the runtime system here we just registered with pin to call this instruction function when it is about to do instrumentation and in this pin at phini function you are registering a call to the phini function when it is about to end and pin so till this point the application has not started neither as the instrumentation and when we do pin start program so this function never returns actually okay so this return zero is just for compilers it's a long jump isn't it so this return is just to make the compiler happy this never returns so that one is a long jump okay and it basically when this function execute it starts the application starts the instrumentation process okay so these two functions would always be there in your pin to and you would add instrumentation routines and okay now let's come into the instrumentation point so if you remember that here the second argument was the instrumentation point okay so this insert call was taking the instruction reference as one of the first input then an instrumentation point and the third argument was the analysis routine so the instruction point actually it refers to a position relative to the instruction so if we look at this JLE instruction so there are three positions so so it says so whenever we are inserting call to analysis routine so we can say whether we want to insert call to analysis routine before this function before this instruction or after this instruction okay so before this instruction so we had in the last example we had given I point before okay so it will insert the call to do come function over here okay corresponding to this JLE instruction the after there are two positions because this is a branch instruction the fall through edge the fall through edge follows is the next instruction in the source and the target is this edge is called the taken edge okay so for the fall through edge we could use I point after and for the taken edge we can use I point taken branch okay so if here we would have given I point after then what would have happened is that this okay if we have given I point after then this counter plus plus would have come here okay it would have happened in Saturday so this is this is a problem only with branches doesn't mean it is in the after a branch there could be two possibilities depending on which way the branch goes okay so both of these may not be even defined for some instructions so if this is a unconditional jump okay so there is no fall through edge after it okay so because it will always jump so I point fall through edge I point after is not valid if this is a conditional branch unconditional branch only the taken edge is valid or or if this is not a compare if it is not a branch instruction like this is a compare instruction there is no taken edge here okay there is only fall through edge here so these two may not be defined for each instruction but I point before is always defined for an instruction most of us in the previous example instead of I point before I specify I point after will so that may it will compile correctly right yeah it will compile correctly but so it will not be able to count the taken branches so you would have to actually somehow modify your instrumentation code so what if I specify both yeah you would have to specify both so in that case will they be counting for non branch instruction no right because the other part does not exist will you understand what servers say suppose that in this example here we do not want to insert call before the instruction we want to insert it after the instruction so if we give only I point after so what may happen is that for conditional branches I mean this counter plus plus would never be executed if the branch is taken for conditional branches yeah yeah for conditional branches if the branch is taken then the counter plus plus which is just after it would not be executed so we would insert the counter plus plus on both these parts I point after and the taken branch so maybe I clarify one thing we talked about this branch delay slot last time makes sense it does not have anything of that sort it submits specific thing so here there is no delay slot just to be very clear so most of the time we would be using I point before but some for branch predictor study we may have to instrument use these use these so for example if you want to know just given a branch how many times you take the fall through how many times you take the taken part then these two will be very important otherwise you can of course use I point we can even do that with I point yeah right so at I point so now let us look at another example so this here we want to print the instruction trace the instruction trace I mean the instruction address for the instructions executed so we would insert call to this print I P function and we will supply an input argument as I P so here we need to pass an input argument to the analysis in the previous case we were not passing any input argument so just for classification just about background in the Indian world I P refers to instruction instruction point same as program which is just printing the instruction pointer of instruction so this tool also works in a similar fashion this is how we will use it I trace dot so we will write a program I for it and it will so it is just printing it is not outputting anything on the standard output or terminal basically writes in this I trace dot out file so when you run it it will create this I trace dot out file and this I am showing some part of the I trace dot out so it will print the instruction addresses in acceleration see the first four instructions first four instruction addresses I P is the I P is the I P is the I P is the instruction pointer which I P will provide it will compute I P it will print I P is the I P is the function we would analysis function that we will supply so here just one we go back to trace so the first instruction is one byte is it first instruction is one byte second one is three byte second one is pretty large I P nine one P four this may be a jump this could be a jump ok so x86 instructions are not of the same size they are variable size instructions yeah it is hard to say ok so this is the code for this is also taken from the sample ok so here the analysis routine is print I P so it is taking an input argument I P ok and it is just printing the this I P ok the the here this code is almost same except that we are creating a file it is not I when the program starts and in the phoenix we are just closing this file ok and the instrumentation registration is almost same the phoenix so look at the instrumentation function this has changed so here we have some more arguments we are passing some other arguments to the this INS insert call function we are passing IR instructions for it ok so this is the these are so what would happen what I here we are saying that so we are asking print to insert a inject a call to print IP function and we are asking it to pass IR instruction pointer as a input to the print IP function ok so it will IR instruction pointer is defined by the pin API it actually gives you the instruction for the current instruction whatever it is instrumenting ok global environment you know it is a it is a what is that type has to be like is it for example in main can I access IR instruction pointer in main no so this is kind of a I would say hash defined so anyway ok so I am just saying that it just gets basically pin provides API function INS address to that function if you provide the instruction reference as input it will give you the address it is a macro yeah it is a macro IR instruction pointer is a macro and it is just saying that inject a call to print IP function and give this instruction pointer as an input to it ok this analysis function can have any number of arguments yeah this analysis so analysis function can have any number of arguments and we can so in the INS insert call we specify what all arguments we want to pass the first three arguments to these always most of the time are changed the first one is the instruction the second one is the instrumentation point the third one is the analysis function that we want to and after the analysis function we can specify any number of arguments we want to pass to the print IP analysis function and IR again actually is a macro which specifies the end of the arguments to INS insert call ok so whatever is between print IP and IR again would be passed as input to print IP function for example if I wanted to pass a file pointer this would make me robot yeah you can do that so yeah if I define file pointer over here it will be available to this I open it with the instruction yeah and then pass it so yeah you can do that ok so is this clear yeah so example of arguments to analysis routine so we can pass an integer value so we can we could have written I have not shown the ok so this is what INS insert one so these two arguments are still almost the same if you want to pass a 32 bit integer value to this function as an input we could say IR UN32 and then we could 6 ok so what this is saying is that it is used like this so these macros some of these this IN32 macro this is not supplied alone just like IR it is supplied with a value ok so you have to give the value also with it so you give UN32 and then the value after a comma the value so it will pass the value 6 as a 32 bit integer value to the analysis function see it can be a variable also yeah it cannot be a constant yeah it can be a variable also that's the problem yeah so it is so this is just the type of ok and IR instruction point is a macro it is actually so transformed into IR UN32 comma INS address instruction ok and there are other so we can also pass register values to functions I am not shown examples of these but IR register value and then the register name so pin would pass the value and we can pass the branch target address so this is also a macro it will get the branch instruction from the instruction the branch target address from the instruction and it will pass it as a 32 bit it will pass it as an instruction value to the function and we can even pass memory address we would see exam how to use them further and there are many more you can pass any number of arguments just stop now one more example ok so till now we have been instrumenting we have been inserting code just at each instruction ok so if you want to do a cache simulation ok we want to print a memory trace so we want to insert code to print so suppose that we are doing memory trace ok so we want to insert just before each load store instruction not before ALU instruction ok we want to insert code specific to some instruction so instrument what a memory trace is first just a sequence of yeah so this is the memory trace so this is the instruction address so this instruction PC value and the memory trace is saying that this instruction did a read from this memory address ok so similarly this instruction did a write on this memory address this is the memory trace so we want to collect this memory trace ok and so till now we were instrumenting at each instruction but if we can collect memory trace through that mechanism also but that would be inefficient there are lot of almost one those are all the instructions are memory instruction we do not want to instrument it ok we want to instrument only the instructions which are load store instructions ok so this tool pinna trace does that prints the memory trace it is also there in the pinkit and this is the code for it kind of do you want to take it out next time so I have put a link to link to our code website how do we start playing this is the website yeah it is linked up with the code website also there is a manual there on the website all these examples have been taken from that manual kind of a tutorial we should go through that tutorial so we will finish this up next time this is the outsize tutorial for you once we are done we will post the course for more