dblaikie added a comment.
In D94064#2481925 <https://reviews.llvm.org/D94064#2481925>, @labath wrote:
> I don't think that simply setting func_lo_pc to zero will be sufficient to
> make this work. I would expect this to break in more complicated scenarios
> (like, even if we just have two of these functions). I think the only reason
> it works in this case is because for this particular function, it's base
> address (relative to the CU base) *is* zero.
I certainly don't have high confidence in the change, to be sure - but I think
it's a bit more robust than that.
Here's at least one experiment where a function is at a non-zero offset
relative to the CU:
$ cat test.cpp
void stop() {
}
void f1() {
int i = 7;
stop();
}
int main() {
int j = 12;
f1();
stop();
}
$ $ clang++-tot test.cpp -gdwarf-5 -mllvm -always-use-ranges-in-v5=Enable &&
~/dev/llvm/build/default/bin/lldb ./a.out
(lldb) target create "./a.out"
Current executable set to '/usr/local/google/home/blaikie/dev/scratch/a.out'
(x86_64).
(lldb) r
Process 1039251 launched: '/usr/local/google/home/blaikie/dev/scratch/a.out'
(x86_64)
Process 1039251 exited with status = 0 (0x00000000)
(lldb) b stop
Breakpoint 1: where = a.out`stop() + 4 at test.cpp:2:1, address =
0x0000000000401114
(lldb) r
Process 1039605 launched: '/usr/local/google/home/blaikie/dev/scratch/a.out'
(x86_64)
Process 1039605 stopped
* thread #1, name = 'a.out', stop reason = breakpoint 1.1
frame #0: 0x0000000000401114 a.out`stop() at test.cpp:2:1
1 void stop() {
-> 2 }
3 void f1() {
4 int i = 7;
5 stop();
6 }
7 int main() {
(lldb) up
frame #1: 0x0000000000401134 a.out`f1() at test.cpp:5:3
2 }
3 void f1() {
4 int i = 7;
-> 5 stop();
6 }
7 int main() {
8 int j = 12;
(lldb) p i
(int) $0 = 7
(lldb) c
Process 1039605 resuming
Process 1039605 stopped
* thread #1, name = 'a.out', stop reason = breakpoint 1.1
frame #0: 0x0000000000401114 a.out`stop() at test.cpp:2:1
1 void stop() {
-> 2 }
3 void f1() {
4 int i = 7;
5 stop();
6 }
7 int main() {
(lldb) up
frame #1: 0x0000000000401159 a.out`main at test.cpp:10:3
7 int main() {
8 int j = 12;
9 f1();
-> 10 stop();
11 }
(lldb) p j
(int) $1 = 12
$ llvm-dwarfdump a.out
.debug_info contents:
0x00000000: Compile Unit: length = 0x0000005f, format = DWARF32, version =
0x0005, unit_type = DW_UT_compile, abbr_offset = 0x0000, addr_size = 0x08 (next
unit at 0x00000063)
0x0000000c: DW_TAG_compile_unit
DW_AT_producer ("clang version 12.0.0
([email protected]:llvm/llvm-project.git
13740c7d80e6c7b47506fd34cd2ea2a7b658cdfa)")
DW_AT_language (DW_LANG_C_plus_plus_14)
DW_AT_name ("test.cpp")
DW_AT_str_offsets_base (0x00000008)
DW_AT_stmt_list (0x00000000)
DW_AT_comp_dir ("/usr/local/google/home/blaikie/dev/scratch")
DW_AT_low_pc (0x0000000000401110)
DW_AT_high_pc (0x0000000000401161)
DW_AT_addr_base (0x00000008)
DW_AT_rnglists_base (0x0000000c)
0x00000027: DW_TAG_subprogram
DW_AT_low_pc (0x0000000000401110)
DW_AT_high_pc (0x0000000000401116)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_linkage_name ("_Z4stopv")
DW_AT_name ("stop")
DW_AT_decl_file
("/usr/local/google/home/blaikie/dev/scratch/test.cpp")
DW_AT_decl_line (1)
DW_AT_external (true)
0x00000033: DW_TAG_subprogram
DW_AT_ranges (indexed (0x0) rangelist = 0x00000014
[0x0000000000401120, 0x000000000040113a))
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_linkage_name ("_Z2f1v")
DW_AT_name ("f1")
DW_AT_decl_file
("/usr/local/google/home/blaikie/dev/scratch/test.cpp")
DW_AT_decl_line (3)
DW_AT_external (true)
0x0000003b: DW_TAG_variable
DW_AT_location (DW_OP_fbreg -4)
DW_AT_name ("i")
DW_AT_decl_file
("/usr/local/google/home/blaikie/dev/scratch/test.cpp")
DW_AT_decl_line (4)
DW_AT_type (0x0000005e "int")
0x00000046: NULL
0x00000047: DW_TAG_subprogram
DW_AT_ranges (indexed (0x1) rangelist = 0x00000018
[0x0000000000401140, 0x0000000000401161))
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_name ("main")
DW_AT_decl_file
("/usr/local/google/home/blaikie/dev/scratch/test.cpp")
DW_AT_decl_line (7)
DW_AT_type (0x0000005e "int")
DW_AT_external (true)
0x00000052: DW_TAG_variable
DW_AT_location (DW_OP_fbreg -4)
DW_AT_name ("j")
DW_AT_decl_file
("/usr/local/google/home/blaikie/dev/scratch/test.cpp")
DW_AT_decl_line (8)
DW_AT_type (0x0000005e "int")
0x0000005d: NULL
0x0000005e: DW_TAG_base_type
DW_AT_name ("int")
DW_AT_encoding (DW_ATE_signed)
DW_AT_byte_size (0x04)
0x00000062: NULL
> The purpose of func_lo_pc is pretty weird, but it's essentially used for
> runtime relocation of location lists within the function -- we take the
> static "base" of the function, and the runtime "base", and the difference
> between the two produces the load bias. Applying the same bias to all
> variable location lists "relocates" the variables. (The reason this is so
> convoluted is reading location lists straight from (unrelocated) .o files on
> mac. I seriously considered changing this when working on debug_rnglists, but
> it turned out it wasn't really necessary, so I let it go.)
Yep, I figured a bunch of this was for DWARF in unrelocated MachO files - and
that they wouldn't be able to/want to use Split DWARF or this feature (which is
particularly relevant to Split DWARF). Does any of this logic apply outside
that unrelocated MachO scenario?
> The "runtime" function address is being taken in
> https://github.com/llvm/llvm-project/blob/main/lldb/source/Core/ValueObjectVariable.cpp#L159
> (and maybe a couple of other places), and these two things need to be in
> sync. I think this could just be defined as the first address in the first
> address range of the function. That should be fine for ELF purposes (I have a
> feeling this thing would completely break down if macho started rearranging
> parts of the function), but it does bring up another problem.
>
> LLDB's representation of a function (lldb_private::Function) assumes that all
> functions will be contiguous (Function::GetAddressRange returns a single
> range). If we make it so that this range matches the first block of the
> function (maybe that's what happens now),
Actually seems to adjust for discontiguous ranges and not just pick the start
of the first (as it appears in the DWARF - which isn't guaranteed to be ordered
in any way) range, instead finding the smallest and largest addresses:
https://github.com/llvm-mirror/lldb/blob/master/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp#L2357
> then maybe we could make things work for the case where DW_AT_ranges are used
> as a size optimization. However, getting things to work for truly
> discontinuous functions will require more work...
>
> (Regarding the test, I think we could avoid running a binary by testing this
> via the "image lookup --verbose" command, and checking that the output
> contains the variables it should.)
Ah, sure thing - I've updated it that way.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D94064/new/
https://reviews.llvm.org/D94064
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits