-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[lldb] Expose discontinuous functions through SBFunction::GetRanges #117532
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,182 @@ | ||
| # REQUIRES: x86 | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any way we can have an architecture-independent test? If it's a ton of work, I say don't worry about it, most folks are going to build the x86 target probably.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The (only?) easy way would be to use a compiler to generate that, but I don't like the tradeoffs that come with that: the Using the compiler to generate the input also reduces our control over it, which means any assertion would have to be fairly loose to avoid the test breaking with compiler changes (we definitely couldn't assert the exact ranges, and even checking their count might too brittle). |
||
|
|
||
| # RUN: split-file %s %t | ||
| # RUN: llvm-mc -triple x86_64-pc-linux -filetype=obj %t/input.s -o %t/input.o | ||
| # RUN: %lldb %t/input.o -o "command script import %t/script.py" -o exit | FileCheck %s | ||
|
|
||
| # CHECK: Found 1 function(s). | ||
| # CHECK: foo: [input.o[0x0-0x7), input.o[0x7-0xe), input.o[0x14-0x1b), input.o[0x1b-0x1c)] | ||
|
|
||
| #--- script.py | ||
| import lldb | ||
|
|
||
| def __lldb_init_module(debugger, internal_dict): | ||
| target = debugger.GetSelectedTarget() | ||
| sym_ctxs = target.FindFunctions("foo") | ||
| print(f"Found {len(sym_ctxs)} function(s).") | ||
| for ctx in sym_ctxs: | ||
| fn = ctx.function | ||
| print(f"{fn.name}: {fn.GetRanges()}") | ||
|
|
||
| #--- input.s | ||
| # An example of a function which has been split into two parts. Roughly | ||
| # corresponds to this C code. | ||
| # int baz(); | ||
| # int bar() { return 47; } | ||
| # int foo(int flag) { return flag ? bar() : baz(); } | ||
| # The function bar has been placed "in the middle" of foo. | ||
|
|
||
| .text | ||
|
|
||
| .type foo,@function | ||
| foo: | ||
| .cfi_startproc | ||
| cmpl $0, %edi | ||
| je foo.__part.2 | ||
| jmp foo.__part.1 | ||
| .cfi_endproc | ||
| .Lfoo_end: | ||
| .size foo, .Lfoo_end-foo | ||
|
|
||
| foo.__part.1: | ||
| .cfi_startproc | ||
| callq bar | ||
| jmp foo.__part.3 | ||
| .Lfoo.__part.1_end: | ||
| .size foo.__part.1, .Lfoo.__part.1_end-foo.__part.1 | ||
| .cfi_endproc | ||
|
|
||
| bar: | ||
| .cfi_startproc | ||
| movl $47, %eax | ||
| retq | ||
| .cfi_endproc | ||
| .Lbar_end: | ||
| .size bar, .Lbar_end-bar | ||
|
|
||
| foo.__part.2: | ||
| .cfi_startproc | ||
| callq baz | ||
| jmp foo.__part.3 | ||
| .Lfoo.__part.2_end: | ||
| .size foo.__part.2, .Lfoo.__part.2_end-foo.__part.2 | ||
| .cfi_endproc | ||
|
|
||
| foo.__part.3: | ||
| .cfi_startproc | ||
| retq | ||
| .Lfoo.__part.3_end: | ||
| .size foo.__part.3, .Lfoo.__part.3_end-foo.__part.3 | ||
| .cfi_endproc | ||
|
|
||
|
|
||
| .section .debug_abbrev,"",@progbits | ||
| .byte 1 # Abbreviation Code | ||
| .byte 17 # DW_TAG_compile_unit | ||
| .byte 1 # DW_CHILDREN_yes | ||
| .byte 37 # DW_AT_producer | ||
| .byte 8 # DW_FORM_string | ||
| .byte 19 # DW_AT_language | ||
| .byte 5 # DW_FORM_data2 | ||
| .byte 17 # DW_AT_low_pc | ||
| .byte 1 # DW_FORM_addr | ||
| .byte 85 # DW_AT_ranges | ||
| .byte 35 # DW_FORM_rnglistx | ||
| .byte 116 # DW_AT_rnglists_base | ||
| .byte 23 # DW_FORM_sec_offset | ||
| .byte 0 # EOM(1) | ||
| .byte 0 # EOM(2) | ||
| .byte 2 # Abbreviation Code | ||
| .byte 46 # DW_TAG_subprogram | ||
| .byte 0 # DW_CHILDREN_no | ||
| .byte 17 # DW_AT_low_pc | ||
| .byte 1 # DW_FORM_addr | ||
| .byte 18 # DW_AT_high_pc | ||
| .byte 1 # DW_FORM_addr | ||
| .byte 3 # DW_AT_name | ||
| .byte 8 # DW_FORM_string | ||
| .byte 0 # EOM(1) | ||
| .byte 0 # EOM(2) | ||
| .byte 3 # Abbreviation Code | ||
| .byte 46 # DW_TAG_subprogram | ||
| .byte 0 # DW_CHILDREN_no | ||
| .byte 85 # DW_AT_ranges | ||
| .byte 35 # DW_FORM_rnglistx | ||
| .byte 64 # DW_AT_frame_base | ||
| .byte 24 # DW_FORM_exprloc | ||
| .byte 3 # DW_AT_name | ||
| .byte 8 # DW_FORM_string | ||
| .byte 0 # EOM(1) | ||
| .byte 0 # EOM(2) | ||
| .byte 0 # EOM(3) | ||
|
|
||
| .section .debug_info,"",@progbits | ||
| .Lcu_begin0: | ||
| .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit | ||
| .Ldebug_info_start0: | ||
| .short 5 # DWARF version number | ||
| .byte 1 # DWARF Unit Type | ||
| .byte 8 # Address Size (in bytes) | ||
| .long .debug_abbrev # Offset Into Abbrev. Section | ||
| .byte 1 # Abbrev [1] DW_TAG_compile_unit | ||
| .asciz "Hand-written DWARF" # DW_AT_producer | ||
| .short 29 # DW_AT_language | ||
| .quad 0 # DW_AT_low_pc | ||
| .byte 1 # DW_AT_ranges | ||
| .long .Lrnglists_table_base0 # DW_AT_rnglists_base | ||
| .byte 2 # Abbrev [2] DW_TAG_subprogram | ||
| .quad bar # DW_AT_low_pc | ||
| .quad .Lbar_end # DW_AT_high_pc | ||
| .asciz "bar" # DW_AT_name | ||
| .byte 3 # Abbrev [3] DW_TAG_subprogram | ||
| .byte 0 # DW_AT_ranges | ||
| .byte 1 # DW_AT_frame_base | ||
| .byte 86 | ||
| .asciz "foo" # DW_AT_name | ||
| .byte 0 # End Of Children Mark | ||
| .Ldebug_info_end0: | ||
|
|
||
| .section .debug_rnglists,"",@progbits | ||
| .long .Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length | ||
| .Ldebug_list_header_start0: | ||
| .short 5 # Version | ||
| .byte 8 # Address size | ||
| .byte 0 # Segment selector size | ||
| .long 2 # Offset entry count | ||
| .Lrnglists_table_base0: | ||
| .long .Ldebug_ranges0-.Lrnglists_table_base0 | ||
| .long .Ldebug_ranges1-.Lrnglists_table_base0 | ||
| .Ldebug_ranges0: | ||
| .byte 6 # DW_RLE_start_end | ||
| .quad foo | ||
| .quad .Lfoo_end | ||
| .byte 6 # DW_RLE_start_end | ||
| .quad foo.__part.1 | ||
| .quad .Lfoo.__part.1_end | ||
| .byte 6 # DW_RLE_start_end | ||
| .quad foo.__part.2 | ||
| .quad .Lfoo.__part.2_end | ||
| .byte 6 # DW_RLE_start_end | ||
| .quad foo.__part.3 | ||
| .quad .Lfoo.__part.3_end | ||
| .byte 0 # DW_RLE_end_of_list | ||
| .Ldebug_ranges1: | ||
| .byte 6 # DW_RLE_start_end | ||
| .quad bar | ||
| .quad .Lbar_end | ||
| .byte 6 # DW_RLE_start_end | ||
| .quad foo.__part.1 | ||
| .quad .Lfoo.__part.1_end | ||
| .byte 6 # DW_RLE_start_end | ||
| .quad foo.__part.2 | ||
| .quad .Lfoo.__part.2_end | ||
| .byte 6 # DW_RLE_start_end | ||
| .quad foo.__part.3 | ||
| .quad .Lfoo.__part.3_end | ||
| .byte 6 # DW_RLE_start_end | ||
| .quad foo | ||
| .quad .Lfoo_end | ||
| .byte 0 # DW_RLE_end_of_list | ||
| .Ldebug_list_header_end0: | ||
|
|
||
| .section ".note.GNU-stack","",@progbits | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've deleted this because of a combination of a default copy constructor and a non-default assignment operator is very unusual (and it makes the move operations unavailable).