peadar / pstack

Print stack traces from running processes, or core files. Supports aarch64, x86_64, and i386
BSD 2-Clause "Simplified" License
134 stars 34 forks source link

DW_GNU_ENTRY_VALUE issue #4

Closed oylz closed 5 years ago

oylz commented 5 years ago

hi, thanks for you working. I have test pstack, But I see there has some probolem in the implement of DW_GNU_ENTRY_VALUE

peadar commented 5 years ago

I'm going to need some more details of what your problem is. Have you a reproducible problem that I can look at?

oylz commented 5 years ago

thank you for your quickly reply. here is my steps: for now, every argument with wrong value

1.write a cpp file chr_test.cpp

#include <stdio.h>
#include <stdint.h>

int fun(char xxxxchr, int xxxxinteger, uint64_t num, char nxxxxchr){
    fprintf(stderr, "xxxxchr:%x, xxxxinteger:%x, num:%lx, nxxxxchr:%x\n", xxxxchr, xxxxinteger, num, nxxxxchr);
    fprintf(stderr, "enter any key to continue...\n");
    getchar();
    return 1;
 }

 int main(int argc, char **argv){
     fun(110, 222222222, 12345, 111);
     return 0;
 }

2.build with -O2:

g++ -ggdb -O2 -o chr_test chr_test.cpp

3.run chr_test:

./chr_test

the output is:

[root@mq test]# ./chr_test
xxxxchr:6e, xxxxinteger:d3ed78e, num:3039, nxxxxchr:6f
enter any key to continue...

4.use pstack to the pid of chr_test:

./pstack -a 2962

the output is:

process: /proc/2962/mem
thread: 0, lwp: 2962, type: 0
#0  0x00007f6fc7b6af70 in __GI___read!+16() at /lib64/libc.so.6
#1  0x00007f6fc7af7b14 in __GI__IO_file_underflow!+339() at /lib64/libc.so.6
#2  0x00007f6fc7af8ce2 in __GI__IO_default_uflow!+49() at /lib64/libc.so.6
#3  0x00007f6fc7af354e in fgetc!+173() at /lib64/libc.so.6
#4  0x00000000004006db in fun+74(xxxxchr=0{r5}, xxxxinteger=0x7f6fc8887000{r4}, num=0x400{r1}, nxxxxchr=0xffffffffffffffff{r2}) at /usr/local/xyz/mm/test/chr_test at stdio.h:46
#5  0x000000000040059d in main+28(argc=0{r5}, argv=0x7f6fc8887000{r4}) at /usr/local/xyz/mm/test/chr_test at chr_test.cpp:12
#6  0x00007f6fc7a9e3d5 in __libc_start_main!+244() at /lib64/libc.so.6
#7  0x00000000004005cd in <unknown>() at /usr/local/xyz/mm/test/chr_test
peadar commented 5 years ago

Hey sorry for the delay in responding, and thanks for the detail. The problem with DW_OP_gnu_entry_value is that we can't evaluate it in pstack. In a debugger, when you step through your code, you would evaluate these values on entry to the function, so that you have the value later in the function. By the time the code reaches the point in question, the values are no longer present in the state of the process - pstack cant recover them. If you look through the disassembly of the code, you'll see that the values in the registers used to call the function have been trampled over once you enter printf, because they're not used again. If you put the pause before the call to printf, it at least works for most of the arguments (because the values need to be present before the printf call, and the debug info can express their locations without resorting to DW_OP_gnu_entry_value). I did see it get at least one of them wrong though - let me try and track that down.

TLDR: we can't evaluate DW_OP_gnu_entry_value in pstack, because the state is already lost by the time pstack gets there. A debugger doing a live debugging session could do this on entry into each function, but that's beyond the scope of what pstack could do. There should be better reporting for this, and there does seem to be an issue still - I'll look into those .

oylz commented 5 years ago

thank you for your detail reply.I will close this issue.