1# REQUIRES: x86 2 3# RUN: split-file %s %t 4# RUN: llvm-mc -triple x86_64-pc-linux -filetype=obj %t/input.s -o %t/input.o 5# RUN: %lldb %t/input.o -o "command script import %t/script.py" -o exit | FileCheck %s 6 7# CHECK: Found 1 function(s). 8# CHECK: foo: [input.o[0x0-0xe), input.o[0x14-0x1c)] 9# CHECK-NEXT: input.o[0x0]: cmpl $0x0, %edi 10# CHECK-NEXT: input.o[0x3]: je 0x14 11# CHECK-NEXT: input.o[0x5]: jmp 0x7 12# CHECK-NEXT: input.o[0x7]: callq 0xe 13# CHECK-NEXT: input.o[0xc]: jmp 0x1b 14# CHECK-EMPTY: 15# CHECK-NEXT: input.o[0x14]: callq 0x19 16# CHECK-NEXT: input.o[0x19]: jmp 0x1b 17# CHECK-NEXT: input.o[0x1b]: retq 18 19 20#--- script.py 21import lldb 22 23def __lldb_init_module(debugger, internal_dict): 24 target = debugger.GetSelectedTarget() 25 sym_ctxs = target.FindFunctions("foo") 26 print(f"Found {len(sym_ctxs)} function(s).") 27 for ctx in sym_ctxs: 28 fn = ctx.function 29 print(f"{fn.name}: {fn.GetRanges()}") 30 print(fn.GetInstructions(target)) 31 32#--- input.s 33# An example of a function which has been split into two parts. Roughly 34# corresponds to this C code. 35# int baz(); 36# int bar() { return 47; } 37# int foo(int flag) { return flag ? bar() : baz(); } 38# The function bar has been placed "in the middle" of foo. 39 40 .text 41 42 .type foo,@function 43foo: 44 .cfi_startproc 45 cmpl $0, %edi 46 je foo.__part.2 47 jmp foo.__part.1 48 .cfi_endproc 49.Lfoo_end: 50 .size foo, .Lfoo_end-foo 51 52foo.__part.1: 53 .cfi_startproc 54 callq bar 55 jmp foo.__part.3 56.Lfoo.__part.1_end: 57 .size foo.__part.1, .Lfoo.__part.1_end-foo.__part.1 58 .cfi_endproc 59 60bar: 61 .cfi_startproc 62 movl $47, %eax 63 retq 64 .cfi_endproc 65.Lbar_end: 66 .size bar, .Lbar_end-bar 67 68foo.__part.2: 69 .cfi_startproc 70 callq baz 71 jmp foo.__part.3 72.Lfoo.__part.2_end: 73 .size foo.__part.2, .Lfoo.__part.2_end-foo.__part.2 74 .cfi_endproc 75 76foo.__part.3: 77 .cfi_startproc 78 retq 79.Lfoo.__part.3_end: 80 .size foo.__part.3, .Lfoo.__part.3_end-foo.__part.3 81 .cfi_endproc 82 83 84 .section .debug_abbrev,"",@progbits 85 .byte 1 # Abbreviation Code 86 .byte 17 # DW_TAG_compile_unit 87 .byte 1 # DW_CHILDREN_yes 88 .byte 37 # DW_AT_producer 89 .byte 8 # DW_FORM_string 90 .byte 19 # DW_AT_language 91 .byte 5 # DW_FORM_data2 92 .byte 17 # DW_AT_low_pc 93 .byte 1 # DW_FORM_addr 94 .byte 85 # DW_AT_ranges 95 .byte 35 # DW_FORM_rnglistx 96 .byte 116 # DW_AT_rnglists_base 97 .byte 23 # DW_FORM_sec_offset 98 .byte 0 # EOM(1) 99 .byte 0 # EOM(2) 100 .byte 2 # Abbreviation Code 101 .byte 46 # DW_TAG_subprogram 102 .byte 0 # DW_CHILDREN_no 103 .byte 17 # DW_AT_low_pc 104 .byte 1 # DW_FORM_addr 105 .byte 18 # DW_AT_high_pc 106 .byte 1 # DW_FORM_addr 107 .byte 3 # DW_AT_name 108 .byte 8 # DW_FORM_string 109 .byte 0 # EOM(1) 110 .byte 0 # EOM(2) 111 .byte 3 # Abbreviation Code 112 .byte 46 # DW_TAG_subprogram 113 .byte 0 # DW_CHILDREN_no 114 .byte 85 # DW_AT_ranges 115 .byte 35 # DW_FORM_rnglistx 116 .byte 64 # DW_AT_frame_base 117 .byte 24 # DW_FORM_exprloc 118 .byte 3 # DW_AT_name 119 .byte 8 # DW_FORM_string 120 .byte 0 # EOM(1) 121 .byte 0 # EOM(2) 122 .byte 0 # EOM(3) 123 124 .section .debug_info,"",@progbits 125.Lcu_begin0: 126 .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit 127.Ldebug_info_start0: 128 .short 5 # DWARF version number 129 .byte 1 # DWARF Unit Type 130 .byte 8 # Address Size (in bytes) 131 .long .debug_abbrev # Offset Into Abbrev. Section 132 .byte 1 # Abbrev [1] DW_TAG_compile_unit 133 .asciz "Hand-written DWARF" # DW_AT_producer 134 .short 29 # DW_AT_language 135 .quad 0 # DW_AT_low_pc 136 .byte 1 # DW_AT_ranges 137 .long .Lrnglists_table_base0 # DW_AT_rnglists_base 138 .byte 2 # Abbrev [2] DW_TAG_subprogram 139 .quad bar # DW_AT_low_pc 140 .quad .Lbar_end # DW_AT_high_pc 141 .asciz "bar" # DW_AT_name 142 .byte 3 # Abbrev [3] DW_TAG_subprogram 143 .byte 0 # DW_AT_ranges 144 .byte 1 # DW_AT_frame_base 145 .byte 86 146 .asciz "foo" # DW_AT_name 147 .byte 0 # End Of Children Mark 148.Ldebug_info_end0: 149 150 .section .debug_rnglists,"",@progbits 151 .long .Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length 152.Ldebug_list_header_start0: 153 .short 5 # Version 154 .byte 8 # Address size 155 .byte 0 # Segment selector size 156 .long 2 # Offset entry count 157.Lrnglists_table_base0: 158 .long .Ldebug_ranges0-.Lrnglists_table_base0 159 .long .Ldebug_ranges1-.Lrnglists_table_base0 160.Ldebug_ranges0: 161 .byte 6 # DW_RLE_start_end 162 .quad foo 163 .quad .Lfoo_end 164 .byte 6 # DW_RLE_start_end 165 .quad foo.__part.1 166 .quad .Lfoo.__part.1_end 167 .byte 6 # DW_RLE_start_end 168 .quad foo.__part.2 169 .quad .Lfoo.__part.2_end 170 .byte 6 # DW_RLE_start_end 171 .quad foo.__part.3 172 .quad .Lfoo.__part.3_end 173 .byte 0 # DW_RLE_end_of_list 174.Ldebug_ranges1: 175 .byte 6 # DW_RLE_start_end 176 .quad bar 177 .quad .Lbar_end 178 .byte 6 # DW_RLE_start_end 179 .quad foo.__part.1 180 .quad .Lfoo.__part.1_end 181 .byte 6 # DW_RLE_start_end 182 .quad foo.__part.2 183 .quad .Lfoo.__part.2_end 184 .byte 6 # DW_RLE_start_end 185 .quad foo.__part.3 186 .quad .Lfoo.__part.3_end 187 .byte 6 # DW_RLE_start_end 188 .quad foo 189 .quad .Lfoo_end 190 .byte 0 # DW_RLE_end_of_list 191.Ldebug_list_header_end0: 192 193 .section ".note.GNU-stack","",@progbits 194