Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
300 views
in Technique[技术] by (71.8m points)

c - How to check if my debugger's program counter is inside a function?

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
", 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, &regs ) == -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?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...