llvm / llvm/llvm-project

Step into in a function call from a shared library steps to the plt record, not to the corresponding code

Open
#170,810 4 comments 0 reactions 0 assignees View on GitHub
lldb
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

I tried to debug the following C++ code:

```c++
1675 std::vector x = {1, 2, 3};
-> 1676 std::sort(x.begin(), x.end());
```

compiled with `g++ 11.4.0-2ubuntu1~20.04` and linked against `libstdc++` into a shared library (`.so` file).

LLDB version:
```
(lldb) version
lldb version 21.1.5 (https://github.com/llvm/llvm-project.git revision 8e2cd28cd4ba46613a46467b0c91b1cabead26cd)
clang revision 8e2cd28cd4ba46613a46467b0c91b1cabead26cd
llvm revision 8e2cd28cd4ba46613a46467b0c91b1cabead26cd
```

The `target.process.thread.step-avoid-regexp` option is totally disabled:

```
(lldb) settings show target.process.thread.step-avoid-regexp
target.process.thread.step-avoid-regexp (regex) = ""
```

I'm trying to get into the `std::sort` function, the `s` command doesn't work due to the absence of the debug information for the standard library. I'm trying to step info with force and get to the corresponding `plt` (`.plt.got`, actually):

```
(lldb) s -a false
Process 3327735 stopped
* thread #7, name = 'JIT Thread', stop reason = step in
frame #0: 0x00007ffff46f3890 libarkcompiler.so`___lldb_unnamed_symbol_a1d900 + 200592
libarkcompiler.so`___lldb_unnamed_symbol_a1d900:
-> 0x7ffff46f3890 <+200592>: endbr64
0x7ffff46f3894 <+200596>: jmpq *0xf68f2e(%rip) ; _GLOBAL_OFFSET_TABLE_ + 100320
0x7ffff46f389a <+200602>: nopw (%rax,%rax)
0x7ffff46f38a0 <+200608>: endbr64
```

I get into the deserved sources only after pressing `s` two times more:

```
* thread #7, name = 'JIT Thread', stop reason = instruction step into
frame #0: 0x00007ffff699a3f2 libarkruntime.so`std::vector>::end(this=size=0) at stl_vector.h:829:7
826 * element order.
827 */
828 iterator
-> 829 end() _GLIBCXX_NOEXCEPT
830 { return iterator(this->_M_impl._M_finish); }
831
```

What I see, when I'm trying to find all the available `std::vector>::end()` symbols in my images:

```
(lldb) im look -r -s "std::vector>::end\(\)$"
1 symbols match the regular expression 'std::vector>::end\(\)$' in .../out/dbg-llvm/lib/libarkbase.so:
Address: libarkbase.so[0x0000000000071f54] (libarkbase.so.PT_LOAD[1]..text + 337396)
Summary: libarkbase.so`std::vector>::end() at stl_vector.h:829:7

2 symbols match the regular expression 'std::vector>::end\(\)$' in .../out/dbg-llvm/lib/libarkcompiler.so:
Address: libarkcompiler.so[0x0000000000b302c4] (libarkcompiler.so.PT_LOAD[1]..text + 473828)
Summary: libarkcompiler.so`std::vector>::end() at stl_vector.h:829:7
Address: libarkcompiler.so[0x00000000009aefc0] (libarkcompiler.so.PT_LOAD[1]..plt + 200608)
Summary: libarkcompiler.so`symbol stub for: std::vector>::end()

2 symbols match the regular expression 'std::vector>::end\(\)$' in .../out/dbg-llvm/lib/libarkruntime.so:
Address: libarkruntime.so[0x00000000012de3f2] (libarkruntime.so.PT_LOAD[1]..text + 863346)
Summary: libarkruntime.so`std::vector>::end() at stl_vector.h:829:7
Address: libarkruntime.so[0x000000000112ecf0] (libarkruntime.so.PT_LOAD[1]..plt + 195792)
Summary: libarkruntime.so`symbol stub for: std::vector>::end()
```

I believe, the deserved symbol is:

```
2 symbols match the regular expression 'std::vector>::end\(\)$' in .../out/dbg-llvm/lib/libarkcompiler.so:
...
Address: libarkcompiler.so[0x00000000009aefc0] (libarkcompiler.so.PT_LOAD[1]..plt + 200608)
Summary: libarkcompiler.so`symbol stub for: std::vector>::end()
```
instead of the corresponding record in `.text`.

What confused me a bit and may be related to the root cause. In the output of `(lldb) im look -r -s "std::vector>::end\(\)$"` I see `libarkcompiler.so.PT_LOAD[1]..plt + 200608` what looks as true:

`200608` is `0x30fa0`, `0x000000000112ecf0 - 0x30fa0 = 97ea020`, this the start of the `.plt` section in the elf file `libarkcompiler.so`:

```
$ readelf -S lib/libarkcompiler.so

[Nr] Name Type Address Offset Size EntSize Flags Link Info Align
[11] .plt PROGBITS 000000000097e020 0097e020 000000000009eef0 0000000000000010 AX 0 0 16
[12] .plt.got PROGBITS 0000000000a1cf10 00a1cf10 00000000000009f0 0000000000000010 AX 0 0 16
```

But in the debug session, once I've done `s -a false`, I got the following:

```
(lldb) s -a false
Process 3360935 stopped
* thread #7, name = 'JIT Thread', stop reason = step in
frame #0: 0x00007ffff46f3890 libarkcompiler.so`___lldb_unnamed_symbol_a1d900 + 200592
libarkcompiler.so`___lldb_unnamed_symbol_a1d900:
-> 0x7ffff46f3890 <+200592>: endbr64
```

`200592 (0x30f90)` is the offset to `$rip (0x7ffff46f3890)`, the pc at the start of the corresponding PLT record, from the start of the **loaded** `.plt.got` section:

```
(lldb) im dump sections libarkcompiler.so
0x00000006 libarkcompiler.so.PT_LOAD[1]..plt
0x000000000000000c code [0x00007ffff46c1f10-0x00007ffff46c2900)
7ffff46f3890

0x00000006 libarkcompiler.so.PT_LOAD[1]..plt.got
0x000000000000000d code [0x00007ffff46c2900-0x00007ffff47617e0)
7ffff46f3890
yep, 30f90 or 200592

0x00000006 libarkcompiler.so.PT_LOAD[1]..plt.sec
0x000000000000000e code [0x00007ffff47617e0-0x00007ffff51116b8) r-x 0x00abc7e0 0x009afed8
```

Actually, `___lldb_unnamed_symbol_a1d900` is the start of the **loaded** `plt.got` section while `a1d900` is the file address of the start of the `.plt.sec`:

```
$ readelf -S lib/libarkcompiler.so | grep 1d900
[13] .plt.sec PROGBITS 0000000000a1d900 00a1d900
```

How it looks in the debugger:

```
(lldb) disassemble -c 30
libarkcompiler.so`___lldb_unnamed_symbol_a1d900:
0x7ffff46c2900 <+0>: endbr64
0x7ffff46c2904 <+4>: jmpq *0xf816f6(%rip) ; _GLOBAL_OFFSET_TABLE_ + 24
0x7ffff46c290a <+10>: nopw (%rax,%rax)
...
```

Contributor guide

Open the contributing guide

Research direction

Reproduce the stepping behavior with the shared-library C++ example, using `s -a false`, `target.process.thread.step-avoid-regexp`, `image lookup`, and section disassembly. Compare the PLT or `.plt.got` stop with the resolved `std::vector::end()` code and determine whether stepping should reach the corresponding `.text` symbol instead; done when the behavior is explained and covered by an appropriate LLDB regression test.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.