I'm writing a debugger and want to see if its program counter is inside a function. I guess I need to check that it's between DW_AT_low_pc
and DW_AT_high_pc
. Here's the code I'm trying to debug:
void myPrint()
{
int test_a = 3;
int test_b = 2;
printf( "myPrint: sum: %d\n", test_a + test_b );
}
int main( void )
{
myPrint();
return 0;
}
dwarfdump
gives the following:
< 1><0x0000033d> DW_TAG_subprogram
DW_AT_external yes(1)
DW_AT_name myPrint
DW_AT_decl_file 0x00000001 /home/glaze/Documents/src/debugger/test_input.c
DW_AT_decl_line 0x0000000d
DW_AT_decl_column 0x00000006
DW_AT_low_pc 0x00001181
DW_AT_high_pc <offset-from-lowpc>66
DW_AT_frame_base len 0x0001: 9c: DW_OP_call_frame_cfa
DW_AT_GNU_all_tail_call_sites yes(1)
DW_AT_sibling <0x0000037a>
In my debugger loop I read the program counter as follows:
struct user_regs_struct regs;
if (ptrace( PTRACE_GETREGS, pid, 0, ®s ) == -1)
{
printf( "%s", strerror( errno ) );
return 1;
}
Elf64_Addr programCounter = regs.rip;
But it gets values that are never between DW_AT_low_pc
and DW_AT_high_pc
, like 0x7f9b94c95100
.
I can already programmatically read DW_AT_low_pc
and DW_AT_high_pc
inside my debugger program and it reports the same values as dwarfdump
.
How do I check that my program counter is inside myPrint
function?
I solved this by taking the program's base address by reading the first line of /proc/pid/maps
and adding it to DW_AT_low_pc
. DW_AT_high_pc
is an offset from DW_AT_low_pc
.
Then in my debugger loop I ran it single-stepped with
ptrace( PTRACE_SINGLESTEP, pid, NULL, NULL );
At each iteration, I checked that the program counter regs.rip
is between the function address range.
Debugging the issue was easier when I compiled the test program with -g -fno-pic -O0 -fPIE
and in the debugger program disabled address space randomization by calling personality( ADDR_NO_RANDOMIZE );
just before ptrace( PTRACE_TRACEME, 0, NULL, NULL );
. I also made the test program more complex by writing a simple adding loop so that it does also something else than calling library routines like printf()
whose addresses are outside of my executable.
User contributions licensed under CC BY-SA 3.0