memoryarchitecturedwarfintel-pindynamic-analysis

Getting the stack pointer content using Intel's PinTool


Using objdump utility, we are able to retrieved the relative address of a variable for example consider a simple C program: Source-code:

#include<stdio.h>
void do_stuff(int my_arg){
    int my_local=my_arg+2;
    int i;
    for(i=0;i<my_local;i++)
        printf("i=%d\n",i);
}

int main(){
    do_stuff(2);
    return 0;
}

Compile with gcc :

$ gcc -g example.c -o example

Run objdump utility with dwarf flag for ELF information.

$objdump --dwarf=info example

Output:

Contents of the .debug_info section:

  Compilation Unit @ offset 0x0:
   Length:        0xd3 (32-bit)
   Version:       4
   Abbrev Offset: 0x0
   Pointer Size:  8
 <0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
    <c>   DW_AT_producer    : (indirect string, offset: 0x0): GNU C 4.8.4 -mtune=generic -march=x86-64 -g -fstack-protector 
    <10>   DW_AT_language    : 1    (ANSI C)
    <11>   DW_AT_name        : (indirect string, offset: 0xcd): sample1.c   
    <15>   DW_AT_comp_dir    : (indirect string, offset: 0x7e): /home/bernard/PhD/TEJAS/tejas_installation_kit/Tejas-Simulator/Tejas/benchmark  
    <19>   DW_AT_low_pc      : 0x40052d 
    <21>   DW_AT_high_pc     : 0x54 
    <29>   DW_AT_stmt_list   : 0x0  
 <1><2d>: Abbrev Number: 2 (DW_TAG_base_type)
    <2e>   DW_AT_byte_size   : 8    
    <2f>   DW_AT_encoding    : 7    (unsigned)
    <30>   DW_AT_name        : (indirect string, offset: 0x47): long unsigned int   
 <1><34>: Abbrev Number: 2 (DW_TAG_base_type)
    <35>   DW_AT_byte_size   : 1    
    <36>   DW_AT_encoding    : 8    (unsigned char)
    <37>   DW_AT_name        : (indirect string, offset: 0x62): unsigned char   
 <1><3b>: Abbrev Number: 2 (DW_TAG_base_type)
    <3c>   DW_AT_byte_size   : 2    
    <3d>   DW_AT_encoding    : 7    (unsigned)
    <3e>   DW_AT_name        : (indirect string, offset: 0xde): short unsigned int  
 <1><42>: Abbrev Number: 2 (DW_TAG_base_type)
    <43>   DW_AT_byte_size   : 4    
    <44>   DW_AT_encoding    : 7    (unsigned)
    <45>   DW_AT_name        : (indirect string, offset: 0x4c): unsigned int    
 <1><49>: Abbrev Number: 2 (DW_TAG_base_type)
    <4a>   DW_AT_byte_size   : 1    
    <4b>   DW_AT_encoding    : 6    (signed char)
    <4c>   DW_AT_name        : (indirect string, offset: 0x64): signed char 
 <1><50>: Abbrev Number: 2 (DW_TAG_base_type)
    <51>   DW_AT_byte_size   : 2    
    <52>   DW_AT_encoding    : 5    (signed)
    <53>   DW_AT_name        : (indirect string, offset: 0xf1): short int   
 <1><57>: Abbrev Number: 3 (DW_TAG_base_type)
    <58>   DW_AT_byte_size   : 4    
    <59>   DW_AT_encoding    : 5    (signed)
    <5a>   DW_AT_name        : int  
 <1><5e>: Abbrev Number: 2 (DW_TAG_base_type)
    <5f>   DW_AT_byte_size   : 8    
    <60>   DW_AT_encoding    : 5    (signed)
    <61>   DW_AT_name        : (indirect string, offset: 0x75): long int    
 <1><65>: Abbrev Number: 2 (DW_TAG_base_type)
    <66>   DW_AT_byte_size   : 8    
    <67>   DW_AT_encoding    : 7    (unsigned)
    <68>   DW_AT_name        : (indirect string, offset: 0xfb): sizetype    
 <1><6c>: Abbrev Number: 2 (DW_TAG_base_type)
    <6d>   DW_AT_byte_size   : 1    
    <6e>   DW_AT_encoding    : 6    (signed char)
    <6f>   DW_AT_name        : (indirect string, offset: 0x6b): char    
 <1><73>: Abbrev Number: 4 (DW_TAG_subprogram)
    <74>   DW_AT_external    : 1    
    <74>   DW_AT_name        : (indirect string, offset: 0x59): do_stuff    
    <78>   DW_AT_decl_file   : 1    
    <79>   DW_AT_decl_line   : 2    
    <7a>   DW_AT_prototyped  : 1    
    <7a>   DW_AT_low_pc      : 0x40052d 
    <82>   DW_AT_high_pc     : 0x3f 
    <8a>   DW_AT_frame_base  : 1 byte block: 9c     (DW_OP_call_frame_cfa)
    <8c>   DW_AT_GNU_all_tail_call_sites: 1 
    <8c>   DW_AT_sibling     : <0xb9>   
 <2><90>: Abbrev Number: 5 (DW_TAG_formal_parameter)
    <91>   DW_AT_name        : (indirect string, offset: 0xd7): my_arg  
    <95>   DW_AT_decl_file   : 1    
    <96>   DW_AT_decl_line   : 2    
    <97>   DW_AT_type        : <0x57>   
    <9b>   DW_AT_location    : 2 byte block: 91 5c  (DW_OP_fbreg: -36)
 <2><9e>: Abbrev Number: 6 (DW_TAG_variable)
    <9f>   DW_AT_name        : (indirect string, offset: 0x3e): my_local    
    <a3>   DW_AT_decl_file   : 1    
    <a4>   DW_AT_decl_line   : 3    
    <a5>   DW_AT_type        : <0x57>   
    <a9>   DW_AT_location    : 2 byte block: 91 6c  (DW_OP_fbreg: -20)
 <2><ac>: Abbrev Number: 7 (DW_TAG_variable)
    <ad>   DW_AT_name        : i    
    <af>   DW_AT_decl_file   : 1    
    <b0>   DW_AT_decl_line   : 4    
    <b1>   DW_AT_type        : <0x57>   
    <b5>   DW_AT_location    : 2 byte block: 91 68  (DW_OP_fbreg: -24)
 <2><b8>: Abbrev Number: 0
 <1><b9>: Abbrev Number: 8 (DW_TAG_subprogram)
    <ba>   DW_AT_external    : 1    
    <ba>   DW_AT_name        : (indirect string, offset: 0x70): main    
    <be>   DW_AT_decl_file   : 1    
    <bf>   DW_AT_decl_line   : 9    
    <c0>   DW_AT_type        : <0x57>   
    <c4>   DW_AT_low_pc      : 0x40056c 
    <cc>   DW_AT_high_pc     : 0x15 
    <d4>   DW_AT_frame_base  : 1 byte block: 9c     (DW_OP_call_frame_cfa)
    <d6>   DW_AT_GNU_all_tail_call_sites: 1 
 <1><d6>: Abbrev Number: 0

I want to do as follows:-

  1. I want to retrieved the address of a variable , say my_local. First I will look into DW_TAG_Variable, then DW_AT_name, DW_AT_location which was given by base register at function -20 from the top.

Question: How to know the content of base register at run time. Can we implement it using PinTool.

Question in broader sense: I want variable my_local map to which address in memory given information from dwarf and Pintool.

Thanks in Advance.


Solution

  • You should be able to use Pin's SafeCopy function to access app memory and copy it into pintool memory.

    But as noted in the comments, it's not always possible to know where variable values are stored reliably so keep this in mind.