Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backtrace in context output is missing symbols compared to "backtrace" output #752

Closed
peace-maker opened this issue May 9, 2020 · 5 comments
Labels

Comments

@peace-maker
Copy link
Contributor

Description

The backtrace shown in the context output isn't showing all the symbol information that's available compared to the output of bt. I'd expect the symbols to be shown in the context view as well.

───────────────────────────────[ BACKTRACE ]───────────────────────────────
 ► f 0     7fd376b7d290
   f 1     7fd376bb057f
   f 2     7fd376b82bf9 sq_call+116
   f 3     561accf89ad8 getargs+588
   f 4     561accf89fcc main+161
   f 5     7fd37699e0b3 __libc_start_main+243
───────────────────────────────────────────────────────────────────────────
pwndbg> bt
#0  0x00007fd376b7d290 in SQVM::Execute(SQObjectPtr&, long long, long long, SQObjectPtr&, unsigned long long, SQVM::ExecutionType)@plt () from /squirrel/build/lib/libsquirrel.so.0                                              
#1  0x00007fd376bb057f in SQVM::Call (this=0x561acd97b820, closure=..., nparams=1, stackbase=2, outres=..., raiseerror=1) at /squirrel/squirrel/sqvm.cpp:1587                                                                    
#2  0x00007fd376b82bf9 in sq_call (v=0x561acd97b820, params=1, retval=1, raiseerror=2) at /squirrel/squirrel/sqapi.cpp:1178                           
#3  0x0000561accf89ad8 in getargs (v=0x561acd97b820, argc=-845694944, argv=0x7fff04254258, retval=0x7fff04254130) at /squirrel/sq/sq.c:193
#4  0x0000561accf89fcc in main (argc=2, argv=0x7fff04254258) at /squirrel/sq/sq.c:330                                                                 
#5  0x00007fd37699e0b3 in __libc_start_main (main=0x561accf89f2b <main>, argc=2, argv=0x7fff04254258, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fff04254248) at ../csu/libc-start.c:308
#6  0x0000561accf8956e in _start ()

Steps to reproduce

FROM ubuntu:latest

ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y build-essential cmake git gdb

RUN git clone https://github.com/albertodemichelis/squirrel.git && \
        cd squirrel && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Debug .. && make
RUN echo 'print("hi there");' > /test.nut

RUN git clone https://github.com/pwndbg/pwndbg.git && \
        cd pwndbg && ./setup.sh

CMD gdb -ex 'start' -ex 'break SQVM::Execute' -ex 'continue' --args squirrel/build/bin/sq test.nut

I've stumbled upon this while debugging a build with debug symbols enabled. Run with docker build -t pwn . && docker run --rm -it --cap-add=SYS_PTRACE pwn and run bt in the gdb shell. Sorry for the big, slow testcase.

My setup

pwndbg> version
Gdb:      9.1
Python:   3.8.2 (default, Apr 27 2020, 15:53:34)  [GCC 9.3.0]
Pwndbg:   1.1.0 build: 5062e4a
Capstone: 4.0.1024
Unicorn:  1.0.1
@pullp
Copy link
Contributor

pullp commented May 11, 2020

How about replace context_backtrace() in commands/context.py with gdb.execute('backtrace') (along with some wrapper code).

Since currrent code use gdb.execute to get the symbol for eache frame. So this change will reduce the usage count of gdb.execute.

If you think this is a good idea, I will make a PR. @disconnect3d

@disconnect3d
Copy link
Member

Just for reference: https://github.com/pwndbg/pwndbg/blob/dev/pwndbg/commands/context.py#L544-L590

Can it be related to symbols being mangled/demangled somewhere and us having incorrect names or something?

Also, what does the current backtrace give us over the original one? Maybe it can show symbols if we synchronize pwndbg with ida? Or handle some corrupted stack trace better and display the addresses?

I think we could try with your approach, though it would be nice to understand why it is made as it is made in the first place and see if we can fix that somehow.

@zachriggle
Copy link
Contributor

Yes, the current backtrace should sync with IDA.

@disconnect3d
Copy link
Member

This is referenced anyway, but just not to loose this: there was an attempt in #754 to fix this.

disconnect3d added a commit that referenced this issue Mar 5, 2023
This commit adds a fix and tests for #1600 and #752.

* #1600
* #752

Generally, for an example like this:

```cpp
struct A {
    void foo(int, int) { };
};

int main() {
    A a;
    a.foo(1, 1);
}
```

The output for `info symbol <address of A::foo>` returns:

```
'A::foo(int, int) [clone.isra.0] + 3 in section .text of /root/pwndbg/tests/gdb-tests/tests/binaries/a.out\n'
```

We then used this code to parse this:

```py
    # Expected format looks like this:
    # main in section .text of /bin/bash
    # main + 3 in section .text of /bin/bash
    # system + 1 in section .text of /lib/x86_64-linux-gnu/libc.so.6
    # No symbol matches system-1.
    a, b, c, _ = result.split(maxsplit=3)

    if b == "+":
        return "%s+%s" % (a, c)
    if b == "in":
        return a

    return ""
```

The `result.split(maxsplit=3)` here splitted the string to:

```py
['A::foo(int,',
 'int)',
 '[clone.isra.0] + 3 in section .text of /root/pwndbg/tests/gdb-tests/tests/binaries/a.out\n']
```

And since `b` was not `"+"` or `"in"` we eventually returned an empty
string instead of the `A::foo(int, int)` which would be expected here.
disconnect3d added a commit that referenced this issue Mar 5, 2023
This commit adds a fix and tests for #1600 and #752.

* #1600
* #752

Generally, for an example like this:

```cpp
struct A {
    void foo(int, int) { };
};

int main() {
    A a;
    a.foo(1, 1);
}
```

The output for `info symbol <address of A::foo>` returns:

```
'A::foo(int, int) [clone.isra.0] + 3 in section .text of /root/pwndbg/tests/gdb-tests/tests/binaries/a.out\n'
```

We then used this code to parse this:

```py
    # Expected format looks like this:
    # main in section .text of /bin/bash
    # main + 3 in section .text of /bin/bash
    # system + 1 in section .text of /lib/x86_64-linux-gnu/libc.so.6
    # No symbol matches system-1.
    a, b, c, _ = result.split(maxsplit=3)

    if b == "+":
        return "%s+%s" % (a, c)
    if b == "in":
        return a

    return ""
```

The `result.split(maxsplit=3)` here splitted the string to:

```py
['A::foo(int,',
 'int)',
 '[clone.isra.0] + 3 in section .text of /root/pwndbg/tests/gdb-tests/tests/binaries/a.out\n']
```

And since `b` was not `"+"` or `"in"` we eventually returned an empty
string instead of the `A::foo(int, int)` which would be expected here.
disconnect3d added a commit that referenced this issue Mar 5, 2023
This commit adds a fix and tests for #1600 and #752.

* #1600
* #752

Generally, for an example like this:

```cpp
struct A {
    void foo(int, int) { };
};

int main() {
    A a;
    a.foo(1, 1);
}
```

The output for `info symbol <address of A::foo>` returns:

```
'A::foo(int, int) [clone.isra.0] + 3 in section .text of /root/pwndbg/tests/gdb-tests/tests/binaries/a.out\n'
```

We then used this code to parse this:

```py
    # Expected format looks like this:
    # main in section .text of /bin/bash
    # main + 3 in section .text of /bin/bash
    # system + 1 in section .text of /lib/x86_64-linux-gnu/libc.so.6
    # No symbol matches system-1.
    a, b, c, _ = result.split(maxsplit=3)

    if b == "+":
        return "%s+%s" % (a, c)
    if b == "in":
        return a

    return ""
```

The `result.split(maxsplit=3)` here splitted the string to:

```py
['A::foo(int,',
 'int)',
 '[clone.isra.0] + 3 in section .text of /root/pwndbg/tests/gdb-tests/tests/binaries/a.out\n']
```

And since `b` was not `"+"` or `"in"` we eventually returned an empty
string instead of the `A::foo(int, int)` which would be expected here.
disconnect3d added a commit that referenced this issue Mar 5, 2023
This commit adds a fix and tests for #1600 and #752.

* #1600
* #752

Generally, for an example like this:

```cpp
struct A {
    void foo(int, int) { };
};

int main() {
    A a;
    a.foo(1, 1);
}
```

The output for `info symbol <address of A::foo>` returns:

```
'A::foo(int, int) [clone.isra.0] + 3 in section .text of /root/pwndbg/tests/gdb-tests/tests/binaries/a.out\n'
```

We then used this code to parse this:

```py
    # Expected format looks like this:
    # main in section .text of /bin/bash
    # main + 3 in section .text of /bin/bash
    # system + 1 in section .text of /lib/x86_64-linux-gnu/libc.so.6
    # No symbol matches system-1.
    a, b, c, _ = result.split(maxsplit=3)

    if b == "+":
        return "%s+%s" % (a, c)
    if b == "in":
        return a

    return ""
```

The `result.split(maxsplit=3)` here splitted the string to:

```py
['A::foo(int,',
 'int)',
 '[clone.isra.0] + 3 in section .text of /root/pwndbg/tests/gdb-tests/tests/binaries/a.out\n']
```

And since `b` was not `"+"` or `"in"` we eventually returned an empty
string instead of the `A::foo(int, int)` which would be expected here.
disconnect3d added a commit that referenced this issue Mar 5, 2023
This commit adds a fix and tests for #1600 and #752.

* #1600
* #752

Generally, for an example like this:

```cpp
struct A {
    void foo(int, int) { };
};

int main() {
    A a;
    a.foo(1, 1);
}
```

The output for `info symbol <address of A::foo>` returns:

```
'A::foo(int, int) [clone.isra.0] + 3 in section .text of /root/pwndbg/tests/gdb-tests/tests/binaries/a.out\n'
```

We then used this code to parse this:

```py
    # Expected format looks like this:
    # main in section .text of /bin/bash
    # main + 3 in section .text of /bin/bash
    # system + 1 in section .text of /lib/x86_64-linux-gnu/libc.so.6
    # No symbol matches system-1.
    a, b, c, _ = result.split(maxsplit=3)

    if b == "+":
        return "%s+%s" % (a, c)
    if b == "in":
        return a

    return ""
```

The `result.split(maxsplit=3)` here splitted the string to:

```py
['A::foo(int,',
 'int)',
 '[clone.isra.0] + 3 in section .text of /root/pwndbg/tests/gdb-tests/tests/binaries/a.out\n']
```

And since `b` was not `"+"` or `"in"` we eventually returned an empty
string instead of the `A::foo(int, int)` which would be expected here.
disconnect3d added a commit that referenced this issue Mar 6, 2023
This commit adds a fix and tests for #1600 and #752.

* #1600
* #752

Generally, for an example like this:

```cpp
struct A {
    void foo(int, int) { };
};

int main() {
    A a;
    a.foo(1, 1);
}
```

The output for `info symbol <address of A::foo>` returns:

```
'A::foo(int, int) [clone.isra.0] + 3 in section .text of /root/pwndbg/tests/gdb-tests/tests/binaries/a.out\n'
```

We then used this code to parse this:

```py
    # Expected format looks like this:
    # main in section .text of /bin/bash
    # main + 3 in section .text of /bin/bash
    # system + 1 in section .text of /lib/x86_64-linux-gnu/libc.so.6
    # No symbol matches system-1.
    a, b, c, _ = result.split(maxsplit=3)

    if b == "+":
        return "%s+%s" % (a, c)
    if b == "in":
        return a

    return ""
```

The `result.split(maxsplit=3)` here splitted the string to:

```py
['A::foo(int,',
 'int)',
 '[clone.isra.0] + 3 in section .text of /root/pwndbg/tests/gdb-tests/tests/binaries/a.out\n']
```

And since `b` was not `"+"` or `"in"` we eventually returned an empty
string instead of the `A::foo(int, int)` which would be expected here.
disconnect3d added a commit that referenced this issue Mar 6, 2023
This commit adds a fix and tests for #1600 and #752.

* #1600
* #752

Generally, for an example like this:

```cpp
struct A {
    void foo(int, int) { };
};

int main() {
    A a;
    a.foo(1, 1);
}
```

The output for `info symbol <address of A::foo>` returns:

```
'A::foo(int, int) [clone.isra.0] + 3 in section .text of /root/pwndbg/tests/gdb-tests/tests/binaries/a.out\n'
```

We then used this code to parse this:

```py
    # Expected format looks like this:
    # main in section .text of /bin/bash
    # main + 3 in section .text of /bin/bash
    # system + 1 in section .text of /lib/x86_64-linux-gnu/libc.so.6
    # No symbol matches system-1.
    a, b, c, _ = result.split(maxsplit=3)

    if b == "+":
        return "%s+%s" % (a, c)
    if b == "in":
        return a

    return ""
```

The `result.split(maxsplit=3)` here splitted the string to:

```py
['A::foo(int,',
 'int)',
 '[clone.isra.0] + 3 in section .text of /root/pwndbg/tests/gdb-tests/tests/binaries/a.out\n']
```

And since `b` was not `"+"` or `"in"` we eventually returned an empty
string instead of the `A::foo(int, int)` which would be expected here.
@disconnect3d
Copy link
Member

This should be fixed by #1605

alufers pushed a commit to alufers/pwndbg that referenced this issue Apr 14, 2023
This commit adds a fix and tests for pwndbg#1600 and pwndbg#752.

* pwndbg#1600
* pwndbg#752

Generally, for an example like this:

```cpp
struct A {
    void foo(int, int) { };
};

int main() {
    A a;
    a.foo(1, 1);
}
```

The output for `info symbol <address of A::foo>` returns:

```
'A::foo(int, int) [clone.isra.0] + 3 in section .text of /root/pwndbg/tests/gdb-tests/tests/binaries/a.out\n'
```

We then used this code to parse this:

```py
    # Expected format looks like this:
    # main in section .text of /bin/bash
    # main + 3 in section .text of /bin/bash
    # system + 1 in section .text of /lib/x86_64-linux-gnu/libc.so.6
    # No symbol matches system-1.
    a, b, c, _ = result.split(maxsplit=3)

    if b == "+":
        return "%s+%s" % (a, c)
    if b == "in":
        return a

    return ""
```

The `result.split(maxsplit=3)` here splitted the string to:

```py
['A::foo(int,',
 'int)',
 '[clone.isra.0] + 3 in section .text of /root/pwndbg/tests/gdb-tests/tests/binaries/a.out\n']
```

And since `b` was not `"+"` or `"in"` we eventually returned an empty
string instead of the `A::foo(int, int)` which would be expected here.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

4 participants