How can i specify an area of code to instrument it by pintool? - intel-pin

There are four levels of granularity in Pin: routine, instruction and image, trace.
Can i specify an limits/area to start and stop inserting instrumentation code.
may by like directive like ( # start instrumentation , # end instrumentation )
or some thing like that,
An example:
for( int i=0; i< x; i++)
{
#startInstrumentation
for( ....;.....;.....)
{
// some code
// function call, conditions , loops, ....
}
#endInstrumentation
}
Is there are any way to do this ?

You can use trace-based instrumentation to do what you want. At the beginning of each trace, check its start address and if it is not in range of interest, avoid adding analysis functions and return immediately from the routine.
It's possible that a trace will begin outside a region of interest but end inside it, or the other way around. If this can happen, you will need to perform more fine grained choice about what to instrument. I would check if this is a real concern before investing an effort.
If you're interested in instrumenting specific routines or images, consider using filter.cpp from InstLib in the kit. An example for use can be found in InstLibExamples.
Now, as for how to target these regions of interest, you have several options. If you have no control over the target binary, you can specify the region in a command line parameter, as a pair of offsets into the image of interest.
If you have control of the binary, you can insert two symbols, that specify the start and end of the rgion of interest, and then iterate over image symbols using the SYM interface.

My solution would be:
1) Insert Region Of Interest (ROI) begin and end functions in code
2) Set a flag after ROI begin is executed and unset it before ROI end is executed
3) Return immediately from instrumenting calls if the flat is unset
Here you have an example where I have modified the memory reference trace to trace only a ROI.
#include <stdio.h>
#include "pin.H"
#include <string>
const CHAR * ROI_BEGIN = "__parsec_roi_begin";
const CHAR * ROI_END = "__parsec_roi_end";
FILE * trace;
bool isROI = false;
// Print a memory read record
VOID RecordMemRead(VOID * ip, VOID * addr, CHAR * rtn)
{
// Return if not in ROI
if(!isROI)
{
return;
}
// Log memory access in CSV
fprintf(trace,"%p,R,%p,%s\n", ip, addr, rtn);
}
// Print a memory write record
VOID RecordMemWrite(VOID * ip, VOID * addr, CHAR * rtn)
{
// Return if not in ROI
if(!isROI)
{
return;
}
// Log memory access in CSV
fprintf(trace,"%p,W,%p,%s\n", ip, addr, rtn);
}
// Set ROI flag
VOID StartROI()
{
isROI = true;
}
// Set ROI flag
VOID StopROI()
{
isROI = false;
}
// Is called for every instruction and instruments reads and writes
VOID Instruction(INS ins, VOID *v)
{
// Instruments memory accesses using a predicated call, i.e.
// the instrumentation is called iff the instruction will actually be executed.
//
// On the IA-32 and Intel(R) 64 architectures conditional moves and REP
// prefixed instructions appear as predicated instructions in Pin.
UINT32 memOperands = INS_MemoryOperandCount(ins);
// Iterate over each memory operand of the instruction.
for (UINT32 memOp = 0; memOp < memOperands; memOp++)
{
// Get routine name if valid
const CHAR * name = "invalid";
if(RTN_Valid(INS_Rtn(ins)))
{
name = RTN_Name(INS_Rtn(ins)).c_str();
}
if (INS_MemoryOperandIsRead(ins, memOp))
{
INS_InsertPredicatedCall(
ins, IPOINT_BEFORE, (AFUNPTR)RecordMemRead,
IARG_INST_PTR,
IARG_MEMORYOP_EA, memOp,
IARG_ADDRINT, name,
IARG_END);
}
// Note that in some architectures a single memory operand can be
// both read and written (for instance incl (%eax) on IA-32)
// In that case we instrument it once for read and once for write.
if (INS_MemoryOperandIsWritten(ins, memOp))
{
INS_InsertPredicatedCall(
ins, IPOINT_BEFORE, (AFUNPTR)RecordMemWrite,
IARG_INST_PTR,
IARG_MEMORYOP_EA, memOp,
IARG_ADDRINT, name,
IARG_END);
}
}
}
// Pin calls this function every time a new rtn is executed
VOID Routine(RTN rtn, VOID *v)
{
// Get routine name
const CHAR * name = RTN_Name(rtn).c_str();
if(strcmp(name,ROI_BEGIN) == 0) {
// Start tracing after ROI begin exec
RTN_Open(rtn);
RTN_InsertCall(rtn, IPOINT_AFTER, (AFUNPTR)StartROI, IARG_END);
RTN_Close(rtn);
} else if (strcmp(name,ROI_END) == 0) {
// Stop tracing before ROI end exec
RTN_Open(rtn);
RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)StopROI, IARG_END);
RTN_Close(rtn);
}
}
// Pin calls this function at the end
VOID Fini(INT32 code, VOID *v)
{
fclose(trace);
}
/* ===================================================================== */
/* Print Help Message */
/* ===================================================================== */
INT32 Usage()
{
PIN_ERROR( "This Pintool prints a trace of memory addresses\n"
+ KNOB_BASE::StringKnobSummary() + "\n");
return -1;
}
/* ===================================================================== */
/* Main */
/* ===================================================================== */
int main(int argc, char *argv[])
{
// Initialize symbol table code, needed for rtn instrumentation
PIN_InitSymbols();
// Usage
if (PIN_Init(argc, argv)) return Usage();
// Open trace file and write header
trace = fopen("roitrace.csv", "w");
fprintf(trace,"pc,rw,addr,rtn\n");
// Add instrument functions
RTN_AddInstrumentFunction(Routine, 0);
INS_AddInstrumentFunction(Instruction, 0);
PIN_AddFiniFunction(Fini, 0);
// Never returns
PIN_StartProgram();
return 0;
}

Related

Receiving a string through UART in STM32F4

I've written this code to receive a series of char variable through USART6 and have them stored in a string. But the problem is first received value is just a junk! Any help would be appreciated in advance.
while(1)
{
//memset(RxBuffer, 0, sizeof(RxBuffer));
i = 0;
requestRead(&dt, 1);
RxBuffer[i++] = dt;
while (i < 11)
{
requestRead(&dt, 1);
RxBuffer[i++] = dt;
HAL_Delay(5);
}
function prototype
static void requestRead(char *buffer, uint16_t length)
{
while (HAL_UART_Receive_IT(&huart6, buffer, length) != HAL_OK)
HAL_Delay(10);
}
First of all, the HAL_Delay seems to be redundant. Is there any particular reason for it?
The HAL_UART_Receive_IT function is used for non-blocking mode. What you have written seems to be more like blocking mode, which uses the HAL_UART_Receive function.
Also, I belive you need something like this:
Somewhere in the main:
// global variables
volatile uint8_t Rx_byte;
volatile uint8_t Rx_data[10];
volatile uint8_t Rx_indx = 0;
HAL_UART_Receive_IT(&huart1, &Rx_byte, 1);
And then the callback function:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == UART1) { // Current UART
Rx_data[Rx_indx++] = Rx_byte; // Add data to Rx_Buffer
}
HAL_UART_Receive_IT(&huart1, &Rx_byte, 1);
}
The idea is to receive always only one byte and save it into an array. Then somewhere check the number of received bytes or some pattern check, etc and then process the received frame.
On the other side, if the number of bytes is always same, you can change the "HAL_UART_Receive_IT" function and set the correct bytes count.

using an integer function return value to return a pointer

I am writing a serial command interpreter. The user will send a text string to the interpreter and it will do stuff and return an integer (either data or a code depending on what the user requested). But I want to expand the interpreter and allow the user to get an array of data or other structure in response to their query.
Can I use the integer return value to return a pointer to EEPROM (or global variable) address? And have the user follow the pointer to the memory location? Based on the query they sent, they would know if the return value is a pointer or data integer.
for example if I want to return
struct curve_t {
int type; // (2 bytes) calibration type indicator
int ref[2]; // (4 bytes) calibration reference point2
float param[11]; // (11*4 bytes) curve fitting parameters
} theCurve;
can I use a function like this?
int serialResponse(char * command) {
// interpret command here
return &theCurve;
}
Can you send a memory address through serial interface?
YES
Can your user access EEPROM through serial interface, using that address?
Not directly. Your MCU has to relay the data between your user and the EEPROM.
I wrote a small test program and confirmed that it is possible. I can pass the address from the function as an integer and then re-cast it in my calling function. It needs to address a global variable or at least on that is available in the calling function.
char res[10];
void loop {
b = function();
Serial.println((char *)b);
}
int function() {
return int(&res[0]);
}
I would not recommend casting a pointer into an integer because it won't work on computer architectures where an int has fewer bits than a pointer.
Lexical Parsers - like what you're writing - often arrange to return a token type, and place the token value in a union that the caller can access. The nice thing about structuring your code in that way is that it's extensible to whatever data types you want, and it will work no matter what C++ platform you're running on.
Here's an example of a token parser that can parse integers and your curve_t:
struct curve_t {
int type; // (2 bytes) calibration type indicator
int ref[2]; // (4 bytes) calibration reference point2
float param[11]; // (11*4 bytes) curve fitting parameters
};
union TokenValue {
int i; // type = TOKEN_TYPE_INT
struct curve_t *pCurve; // type = TOKEN_TYPE_P_CURVE
};
enum TokenType {
TOKEN_TYPE_UNKNOWN = 0,
TOKEN_TYPE_INT,
TOKEN_TYPE_P_CURVE
};
curve_t theCurve;
TokenValue tokenValue;
/*
* Parses the given command,
* setting the parsed value in tokenValue,
* returning the type of value (a TOKEN_TYPE_*).
*/
TokenType serialResponse(char * command) {
if (command[0] == 'a') { // TO DO: your code will test something else.
// We want to return an integer
tokenValue.i = 1234; // TO DO: in your code, instead set the integer value from command
return TOKEN_TYPE_INT;
}
if (command[0] == 'b') { // TO DO: your code will test something else.
// We want to return a pointer to theCurve.
// TO DO: Fill in the values of theCurve, for example theCurve.param[0]
tokenValue.pCurve = &theCurve;
return TOKEN_TYPE_P_CURVE;
}
// Else
return TOKEN_TYPE_UNKNOWN;
}
void setup() {
//TO DO: move this code to where it belongs in your Sketch
//TO DO: parse a command
char command[10] = "and so...";
// TO DO: read the command.
// Process the command
enum TokenType t;
t = serialResponse(command);
if (t == TOKEN_TYPE_INT) {
// The command result is an integer
int i = tokenValue.i;
// TO DO: process the integer.
} else if (t == TOKEN_TYPE_P_CURVE) {
// The command result is a curve
curve_t *pCurve = tokenValue.pCurve;
// TO DO: process the Curve.
} else {
// unrecognized command. TO DO: handle the error.
}
}
void loop() {
// put your main code here, to run repeatedly:
}
If you insist on using the cast of an int to a pointer (which I admit is a lot simpler), you could add a test for int size problems to your setup():
void setup() {
Serial.begin(9600);
if (sizeof(int) < sizeof(curve_t *)) {
Serial.println("cast won't work");
for (;;) {} // hang here forever.
}
}

What does Intel PIN instruction count depend on and why it varies between executions?

I would like to get instruction count for bubblesort algorithm using Intel PIN. I thought that maybe I could analyse how instruction count increases, when there is more data to sort. But the result varies between executions for the same set of data.
For example few outputs: 1662097, 1811453, 1832990, 1745621
It varies quite a lot. Why isn't it the same? Is there a way to achieve it? How am I supposed to get any useful information from that? There is no way of telling how increase of data set influenced number of instructions, when it isn't even stable for the same execution.
Pintool code (copy-pasted from Pin User Guide):
#include <iostream>
#include <fstream>
#include "pin.H"
ofstream OutFile;
// The running count of instructions is kept here
// make it static to help the compiler optimize docount
static UINT64 icount = 0;
// This function is called before every instruction is executed
VOID docount() { icount++; }
// Pin calls this function every time a new instruction is encountered
VOID Instruction(INS ins, VOID *v)
{
// Insert a call to docount before every instruction, no arguments are passed
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)docount, IARG_END);
}
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool",
"o", "inscount.out", "specify output file name");
// This function is called when the application exits
VOID Fini(INT32 code, VOID *v)
{
// Write to a file since cout and cerr maybe closed by the application
OutFile.setf(ios::showbase);
OutFile << "Count " << icount << endl;
OutFile.close();
}
/* ===================================================================== */
/* Print Help Message */
/* ===================================================================== */
INT32 Usage()
{
cerr << "This tool counts the number of dynamic instructions executed" << endl;
cerr << endl << KNOB_BASE::StringKnobSummary() << endl;
return -1;
}
/* ===================================================================== */
/* Main */
/* ===================================================================== */
/* argc, argv are the entire command line: pin -t <toolname> -- ... */
/* ===================================================================== */
int main(int argc, char * argv[])
{
// Initialize pin
if (PIN_Init(argc, argv)) return Usage();
OutFile.open(KnobOutputFile.Value().c_str());
// Register Instruction to be called to instrument instructions
INS_AddInstrumentFunction(Instruction, 0);
// Register Fini to be called when the application exits
PIN_AddFiniFunction(Fini, 0);
// Start the program, never returns
PIN_StartProgram();
return 0;
}
Bubblesort implementation (nothing extraordinary, intentionally O(n^2)):
void bubblesort(int table[], int size) {
int i, j, temp;
for (i = 0; i < size - 1; i++)
{
for (j = 0; j < size - 1 - i; j++)
{
if (table[j] > table[j + 1])
{
temp = table[j + 1];
table[j + 1] = table[j];
table[j] = temp;
}
}
}
}

How to stop the pintool artificially

I want to use the pin to track the address of the first 256*256 instructions, but I don't know how to stop the pin after the number is reached. I know there is a method PIN_ExitProcess(), but make will cause an error after adding it. Is there any other way?
#include <stdio.h>
#include "pin.H"
FILE * trace;
VOID printip(VOID *ip) {
fprintf(trace, "%p\n", ip);
}
VOID Instruction(INS ins, VOID *v)
{
if(0x70000000>INS_Address(ins))
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)printip, IARG_INST_PTR, IARG_END);
}
VOID Fini(INT32 code, VOID *v)
{
fprintf(trace, "#eof\n");
fclose(trace);
}
INT32 Usage()
{
PIN_ERROR("This Pintool prints the IPs of every instruction executed\n"
+ KNOB_BASE::StringKnobSummary() + "\n");
return -1;
}
int main(int argc, char * argv[])
{
trace = fopen("itrace.out", "w");
if (PIN_Init(argc, argv)) return Usage();
INS_AddInstrumentFunction(Instruction, 0);
PIN_AddFiniFunction(Fini, 0);
PIN_StartProgram();
return 0;
}
You have two options:
Simply count the number of traced instructions and stop fprintfing when you reach the threshold using an if statement.
Call PIN_Detach() when the instruction threshold is reached. See more here: https://software.intel.com/sites/landingpage/pintool/docs/97503/Pin/html/group__PIN__CONTROL.html#ga6277d16bf33ede39685a26a92fc3cbef

Arduino Dynamic Two-dimensional array

I'm working on an Arduino project where I need to build (and work with) a two-dimensional array at runtime. I've been poking around looking for a solution, but I've had no luck. I found an example of a dynamic one-dimentional array helper here: http://playground.arduino.cc/Code/DynamicArrayHelper, so i've been trying to adopt that code for my use. I created a library using the following code:
My Header file:
#ifndef Dynamic2DArray_h
#define Dynamic2DArray_h
#include "Arduino.h"
class Dynamic2DArray
{
public:
Dynamic2DArray( bool sorted );
//Add an integer pair to the array
bool add( int v1, int v2);
//Clear out (empty) the array
bool clear();
//Get the array item in the specified row, column
int getValue(int row, int col);
//Get the number of rows in the array
int length();
private:
int _rows;
void * _slots;
bool _sorted;
void _sort();
};
#endif
The library's code:
#include "Arduino.h"
#include "Dynamic2DArray.h"
#define ARRAY_COLUMNS 2
int _rows;
void * _slots;
bool _sorted;
Dynamic2DArray::Dynamic2DArray(bool sorted) {
//Set our local value indicating where we're supposed to
//sort or not
_sorted = sorted;
//Initialize the row count so it starts at zero
_rows = 0;
}
bool Dynamic2DArray::add( int v1, int v2) {
//Add the values to the array
//implementation adapted from http://playground.arduino.cc/Code/DynamicArrayHelper
//Allocate memory based on the size of the current array rows plus one (the new row)
int elementSize = sizeof(int) * ARRAY_COLUMNS;
//calculate how much memory the current array is using
int currentBufferSize = elementSize * _rows;
//calculate how much memory the new array will use
int newBufferSize = elementSize * (_rows + 1);
//allocate memory for the new array (which should be bigger than the old one)
void * newArray = malloc ( newBufferSize );
//Does newArray not point to something (a memory address)?
if (newArray == 0) {
//Then malloc failed, so return false
return false;
}
// copy the data from the old array, to the new array
for (int idx = 0; idx < currentBufferSize ; idx++)
{
((byte*)newArray)[idx] = ((byte *)_slots)[idx];
}
// free the original array
if (_slots != NULL)
{
free(_slots);
}
// clear the newly allocated memory space (the new row)
for (int idx = currentBufferSize; idx < newBufferSize; idx++)
{
((byte *)newArray)[idx] = 0;
}
// Store the number of rows the memory is allocated for
_rows = ++_rows;
// set the array to the newly created array
_slots = newArray;
//Free up the memory used by the new array
free(newArray);
//If the array's supposed to be sorted,
//then sort it
if (_sorted) {
_sort();
}
// success
return true;
};
int Dynamic2DArray::length() {
return _rows;
};
bool Dynamic2DArray::clear() {
//Free up the memory allocated to the _slots array
free(_slots);
//And zero out the row count
_rows = 0;
};
int Dynamic2DArray::getValue(int row, int col) {
//do we have a valid row/col?
if ((row < _rows) && (col < ARRAY_COLUMNS)) {
//Return the array value at that row/col
return _slots[row][col];
} else {
//No? Then there's nothing we can do here
return -1;
}
};
//Sorted probably doesn't matter, I can probably ignore this one
void _sort() {
}
The initial assignment of the _slots value is giving me problems, I don't know how to define it so this code builds. The _slots variable is supposed to point to the dynamic array, but I've got it wrong.
When I try to compile the code into my project's code, I get the following:
Arduino: 1.8.0 (Windows 10), Board: "Pro Trinket 3V/12MHz (USB)"
sketch\Dynamic2DArray.cpp: In member function 'int Dynamic2DArray::getValue(int, int)':
sketch\Dynamic2DArray.cpp:83:22: warning: pointer of type 'void *' used in arithmetic [-Wpointer-arith]
return _slots[row][col];
^
Dynamic2DArray.cpp:83: error: 'void*' is not a pointer-to-object type
Can someone please help me fix this code? I've posted the files to https://github.com/johnwargo/Arduino-Dynamic-2D-Array-Lib.
The code you took was for a 1D dynamic array; the modifications for a 2D array are too tricky. Give up these horrors.
I think there is no reason you use dynamic array. You can assume that size max is ROW_MAX * COL_MAX, so you can define a static array int array[ROW_MAX][COL_MAX].
on one hand if you defined a dynamic array, you could free space when you dont use it anymore and take advantage of it for other work. I dont know if this is your case.
on the other hand if you define a static array (on UNO), you have 32kB available on program space, instead of 2kB available on RAM.
Because of the difference 32kB / 2kB, there are very few chances you can get bigger array with dynamic allocation.

Resources