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

nearpc fails to show the symbol name after demangling #1600

Closed
lebr0nli opened this issue Feb 27, 2023 · 3 comments
Closed

nearpc fails to show the symbol name after demangling #1600

lebr0nli opened this issue Feb 27, 2023 · 3 comments
Assignees
Labels

Comments

@lebr0nli
Copy link
Contributor

lebr0nli commented Feb 27, 2023

When I learning OOP for C++, I found out this:

$ cat test.cpp
#include <iostream>

class A{
public:
    A(int _sz=10);
    A(const A& a);
    ~A();
    A& operator=(const A& a);
private:
    char *p;
    int sz;
};

A::A(int _sz): sz(_sz){
    p = new char[sz];
    std::cout << "ctor" << std::endl;
}

A::A(const A &a) {
    p = new char[sz=a.sz];
    std::cout << "copy" << std::endl;
}

A::~A() {
    delete[] p;
    std::cout << "dtor" << std::endl;
}

A &A::operator=(const A &a) {
    if(this != &a){
        p = new char[sz=a.sz];
        for(int i = 0; i < sz; ++i) p[i] = a.p[i];
    }
    std::cout << "assign" << std::endl;
    return *this;
}

int main() {
    A a1;
    A a2 = a1;
    A a3;
    a3 = a2;
    return 0;
}
$ g++ -ggdb test.cpp
$ gdb -q a.out -ex 'set context-sections' -ex 'break main' -ex 'run' -ex 'nearpc main 15'
...
 ► 0x55f188f603fe <main>        endbr64
   0x55f188f60402 <main+4>      push   rbp
   0x55f188f60403 <main+5>      mov    rbp, rsp
   0x55f188f60406 <main+8>      push   rbx
   0x55f188f60407 <main+9>      sub    rsp, 0x48
   0x55f188f6040b <main+13>     mov    rax, qword ptr fs:[0x28]      <main>
   0x55f188f60414 <main+22>     mov    qword ptr [rbp - 0x18], rax
   0x55f188f60418 <main+26>     xor    eax, eax
   0x55f188f6041a <main+28>     lea    rax, [rbp - 0x50]
   0x55f188f6041e <main+32>     mov    esi, 0xa
   0x55f188f60423 <main+37>     mov    rdi, rax
   0x55f188f60426 <main+40>     call   A::A(int)                <A::A(int)>

   0x55f188f6042b <main+45>     lea    rdx, [rbp - 0x50]
   0x55f188f6042f <main+49>     lea    rax, [rbp - 0x40]
   0x55f188f60433 <main+53>     mov    rsi, rdx
   0x55f188f60436 <main+56>     mov    rdi, rax
   0x55f188f60439 <main+59>     call   0x55f188f6028e                <0x55f188f6028e>

   0x55f188f6043e <main+64>     lea    rax, [rbp - 0x30]
   0x55f188f60442 <main+68>     mov    esi, 0xa
   0x55f188f60447 <main+73>     mov    rdi, rax
   0x55f188f6044a <main+76>     call   A::A(int)                <A::A(int)>

   0x55f188f6044f <main+81>     lea    rdx, [rbp - 0x40]
   0x55f188f60453 <main+85>     lea    rax, [rbp - 0x30]
   0x55f188f60457 <main+89>     mov    rsi, rdx
   0x55f188f6045a <main+92>     mov    rdi, rax
   0x55f188f6045d <main+95>     call   0x55f188f6034c                <0x55f188f6034c>

   0x55f188f60462 <main+100>    mov    ebx, 0
   0x55f188f60467 <main+105>    lea    rax, [rbp - 0x30]
   0x55f188f6046b <main+109>    mov    rdi, rax
   0x55f188f6046e <main+112>    call   A::~A()                <A::~A()>

   0x55f188f60473 <main+117>    lea    rax, [rbp - 0x40]
...

As you can see, nearpc failed to show the symbol name of the copy constructor(at 0x55f188f6028e) and the assignment operator(at 0x55f188f6034c).

It's because the symbol of them after demangling contains spaces and break our logic at here:

a, b, c, _ = result.split(maxsplit=3)
if b == "+":
return "%s+%s" % (a, c)
if b == "in":
return a
return ""

@lebr0nli lebr0nli added the bug label Feb 27, 2023
@disconnect3d
Copy link
Member

Shorter example - compile as g++ -O0 mangling.cpp:

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

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

@disconnect3d disconnect3d self-assigned this Mar 4, 2023
@disconnect3d
Copy link
Member

@disconnect3d
Copy link
Member

disconnect3d commented Mar 4, 2023

To give another example: for the symbol above GDB's info symbol ... returns:

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

And since we split this by 3 spaces we end up with the following split:

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

And we end up returning an empty string here:

    # 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 ""

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.
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

2 participants