1

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.

Bernard Nongpoh
  • 1,028
  • 11
  • 20
  • You can always get the frame address then compute the local variable offset to get the runtime address. However, not all local variables will be saved in dedicated frame address. Sometimes it will be stored only in the register after optimization. If you always use non-optimized code, you should be able to get the variable's address in the frame. For example, you can get __builtin_return_address(n) in GCC and then compute frame address - 20 to get the variable's content. – jclin Sep 06 '16 at 20:57
  • Hello Jclin Thanks for the reply, I am a beginer in pintool as well as dwarf can you elaborate or specify the steps to achieve this – Bernard Nongpoh Sep 07 '16 at 05:29
  • Hello Jclin, I am able to retrieve the stack pointer using pintool at function level. How to calculate from the offset I tried , it matches only for one variable – Bernard Nongpoh Sep 07 '16 at 12:14
  • you only want the address of `my_local` variable, don't you? – jclin Sep 07 '16 at 15:24
  • Hey Jclin, I solved it by retrieving the EBP register content i.e look for EBP index in .frame section, which is ofs 16 so address of my_local= EBP + 16 -20 , Thanks alot it works and now i need to automate this thing by integrating libdwarf and pintool to determine the address automatically – Bernard Nongpoh Sep 07 '16 at 17:48
  • Hey Jclin, How to retrieved offset of a variable from DW_AT_locaion using libdwarf – Bernard Nongpoh Sep 08 '16 at 09:41
  • @BernardNongpoh , if you have follow up questions which are not directly related to this one (eg, how to extract variable offset from DW_AT_location), it is more appropriate to create a new question rather than ask it in a comment. You will probably get an answer sooner as well. – nitzanms Sep 12 '16 at 10:41

1 Answers1

0

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.

nitzanms
  • 1,786
  • 12
  • 35
  • Hello Nitzanms, is there any callback function in pintool that gives function invocation trace. for example if main() calls foo() , foo() call bar() I want to get information like 1.main()->2.foo()-->3.bar() , here bar() is level-3 and main() is level-1. I want to track this info while instrumenting – Bernard Nongpoh Sep 12 '16 at 02:57
  • There's no such API, and in fact it's not trivial to automatically figure out the stack state due to certain edge cases. There are samples in the Pin kit for stack tracers. They should work for simple cases, if you want to adapt them to your needs. – nitzanms Sep 12 '16 at 10:39