Index: include/lldb/Breakpoint/BreakpointResolverName.h =================================================================== --- include/lldb/Breakpoint/BreakpointResolverName.h +++ include/lldb/Breakpoint/BreakpointResolverName.h @@ -52,6 +52,10 @@ lldb::LanguageType language, lldb::addr_t offset, bool skip_prologue); + // Computes the breakpoint address. + std::tuple
ComputeBreakpointAddress(SymbolContext sc, + bool m_skip_prologue); + static BreakpointResolver * CreateFromStructuredData(Breakpoint *bkpt, const StructuredData::Dictionary &data_dict, Index: include/lldb/Core/Architecture.h =================================================================== --- include/lldb/Core/Architecture.h +++ include/lldb/Core/Architecture.h @@ -64,7 +64,7 @@ /// breakpoint is adjusted to the first function address reached /// by both entry points. //------------------------------------------------------------------ - virtual void AdjustBreakpointAddress(const Symbol &func, + virtual void AdjustBreakpointAddress(const SymbolContext &sc, Address &addr) const {} private: Index: lit/Breakpoint/Inputs/ppc64-call-function.s =================================================================== --- /dev/null +++ lit/Breakpoint/Inputs/ppc64-call-function.s @@ -0,0 +1,270 @@ + .text + .abiversion 2 + .file "ppc64-call-function.c" + .globl foo1 + .p2align 4 + .type foo1,@function +foo1: # @foo1 +.Lfunc_begin0: + .file 1 "ppc64-call-function.c" + .loc 1 10 0 # ppc64-call-function.c:10:0 + .cfi_sections .debug_frame + .cfi_startproc +# BB#0: + .loc 1 10 18 prologue_end # ppc64-call-function.c:10:18 + li 3, 1 + blr +.Ltmp0: + .long 0 + .quad 0 +.Lfunc_end0: + .size foo1, .Lfunc_end0-.Lfunc_begin0 + .cfi_endproc + + .globl foo2 + .p2align 4 + .type foo2,@function +foo2: # @foo2 +.Lfunc_begin1: + .loc 1 11 0 # ppc64-call-function.c:11:0 + .cfi_startproc +.Lfunc_gep1: + addis 2, 12, .TOC.-.Lfunc_gep1@ha + addi 2, 2, .TOC.-.Lfunc_gep1@l +.Lfunc_lep1: + .localentry foo2, .Lfunc_lep1-.Lfunc_gep1 +# BB#0: + mflr 0 + std 31, -8(1) + std 0, 16(1) + stdu 1, -112(1) +.Lcfi0: + .cfi_def_cfa_offset 112 +.Lcfi1: + .cfi_offset r31, -8 +.Lcfi2: + .cfi_offset lr, 16 + mr 31, 1 +.Lcfi3: + .cfi_def_cfa_register r31 +.Ltmp1: + .loc 1 11 25 prologue_end # ppc64-call-function.c:11:25 + bl foo1 + nop + .loc 1 11 32 is_stmt 0 # ppc64-call-function.c:11:32 + addi 3, 3, 1 + .loc 1 11 18 # ppc64-call-function.c:11:18 + extsw 3, 3 + addi 1, 1, 112 + ld 0, 16(1) + ld 31, -8(1) + mtlr 0 + blr +.Ltmp2: + .long 0 + .quad 0 +.Lfunc_end1: + .size foo2, .Lfunc_end1-.Lfunc_begin1 + .cfi_endproc + + .globl main + .p2align 4 + .type main,@function +main: # @main +.Lfunc_begin2: + .loc 1 13 0 is_stmt 1 # ppc64-call-function.c:13:0 + .cfi_startproc +# BB#0: + li 3, 0 + stw 3, -12(1) +.Ltmp3: + .loc 1 13 13 prologue_end # ppc64-call-function.c:13:13 + li 3, 0 + blr +.Ltmp4: + .long 0 + .quad 0 +.Lfunc_end2: + .size main, .Lfunc_end2-.Lfunc_begin2 + .cfi_endproc + + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 4.0.1-6 (tags/RELEASE_401/final)" # string offset=0 +.Linfo_string1: + .asciz "ppc64-call-function.c" # string offset=47 +.Linfo_string2: + .asciz "/home/lbianc/mydata2/llvm/tools/lldb/lit/Breakpoint/Inputs" # string offset=69 +.Linfo_string3: + .asciz "foo1" # string offset=128 +.Linfo_string4: + .asciz "int" # string offset=133 +.Linfo_string5: + .asciz "foo2" # string offset=137 +.Linfo_string6: + .asciz "main" # string offset=142 + .section .debug_loc,"",@progbits + .section .debug_abbrev,"",@progbits +.Lsection_abbrev: + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .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 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 39 # DW_AT_prototyped + .byte 25 # DW_FORM_flag_present + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # 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 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lsection_info: +.Lcu_begin0: + .long 121 # Length of Unit + .short 4 # DWARF version number + .long .Lsection_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x72 DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 12 # DW_AT_language + .long .Linfo_string1 # DW_AT_name + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Linfo_string2 # DW_AT_comp_dir + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end2-.Lfunc_begin0 # DW_AT_high_pc + .byte 2 # Abbrev [2] 0x2a:0x19 DW_TAG_subprogram + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 81 + .long .Linfo_string3 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 10 # DW_AT_decl_line + # DW_AT_prototyped + .long 117 # DW_AT_type + # DW_AT_external + .byte 2 # Abbrev [2] 0x43:0x19 DW_TAG_subprogram + .quad .Lfunc_begin1 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 111 + .long .Linfo_string5 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 11 # DW_AT_decl_line + # DW_AT_prototyped + .long 117 # DW_AT_type + # DW_AT_external + .byte 3 # Abbrev [3] 0x5c:0x19 DW_TAG_subprogram + .quad .Lfunc_begin2 # DW_AT_low_pc + .long .Lfunc_end2-.Lfunc_begin2 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 81 + .long .Linfo_string6 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 13 # DW_AT_decl_line + .long 117 # DW_AT_type + # DW_AT_external + .byte 4 # Abbrev [4] 0x75:0x7 DW_TAG_base_type + .long .Linfo_string4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark + .section .debug_ranges,"",@progbits +.Ldebug_range: + .section .debug_macinfo,"",@progbits +.Ldebug_macinfo: +.Lcu_macro_begin0: + .byte 0 # End Of Macro List Mark + .section .debug_pubnames,"",@progbits + .long .LpubNames_end0-.LpubNames_begin0 # Length of Public Names Info +.LpubNames_begin0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 125 # Compilation Unit Length + .long 42 # DIE offset + .asciz "foo1" # External Name + .long 67 # DIE offset + .asciz "foo2" # External Name + .long 92 # DIE offset + .asciz "main" # External Name + .long 0 # End Mark +.LpubNames_end0: + .section .debug_pubtypes,"",@progbits + .long .LpubTypes_end0-.LpubTypes_begin0 # Length of Public Types Info +.LpubTypes_begin0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 125 # Compilation Unit Length + .long 117 # DIE offset + .asciz "int" # External Name + .long 0 # End Mark +.LpubTypes_end0: + + .ident "clang version 4.0.1-6 (tags/RELEASE_401/final)" + .section ".note.GNU-stack","",@progbits + .section .debug_line,"",@progbits +.Lline_table_start0: Index: lit/Breakpoint/ppc64-call-function.test =================================================================== --- /dev/null +++ lit/Breakpoint/ppc64-call-function.test @@ -0,0 +1,14 @@ +# REQUIRES: ppc64le-linux +# +# RUN: llvm-mc -triple=powerpc64le -filetype=obj %p/Inputs/ppc64-call-function.s -o %t.o +# RUN: ld -o %t %t.o +# RUN: lldb-test breakpoints %t %s | FileCheck %s + +breakpoint set -n foo2 --skip-prologue 0 +# CHECK-LABEL: breakpoint set -n foo2 --skip-prologue 0 +# CHECK: Address: {{.*}}`foo2 + 8 + +breakpoint set -n foo2 +# CHECK-LABEL: breakpoint set -n foo2 +# CHECK: Address: {{.*}}`foo2 + 28 + Index: lit/lit.cfg =================================================================== --- lit/lit.cfg +++ lit/lit.cfg @@ -137,6 +137,9 @@ if re.match(r'^arm(hf.*-linux)|(.*-linux-gnuabihf)', config.target_triple): config.available_features.add("armhf-linux") +if re.match(r'^powerpc64le.*linux.*', config.target_triple): + config.available_features.add("ppc64le-linux") + if re.match(r'icc', config.cc): config.available_features.add("compiler-icc") elif re.match(r'clang', config.cc): Index: source/Breakpoint/BreakpointResolverName.cpp =================================================================== --- source/Breakpoint/BreakpointResolverName.cpp +++ source/Breakpoint/BreakpointResolverName.cpp @@ -336,44 +336,10 @@ if (func_list.GetSize()) { for (i = 0; i < func_list.GetSize(); i++) { if (func_list.GetContextAtIndex(i, sc)) { - bool is_reexported = false; - - if (sc.block && sc.block->GetInlinedFunctionInfo()) { - if (!sc.block->GetStartAddress(break_addr)) - break_addr.Clear(); - } else if (sc.function) { - break_addr = sc.function->GetAddressRange().GetBaseAddress(); - if (m_skip_prologue && break_addr.IsValid()) { - const uint32_t prologue_byte_size = - sc.function->GetPrologueByteSize(); - if (prologue_byte_size) - break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); - } - } else if (sc.symbol) { - if (sc.symbol->GetType() == eSymbolTypeReExported) { - const Symbol *actual_symbol = - sc.symbol->ResolveReExportedSymbol(m_breakpoint->GetTarget()); - if (actual_symbol) { - is_reexported = true; - break_addr = actual_symbol->GetAddress(); - } - } else { - break_addr = sc.symbol->GetAddress(); - } - - if (m_skip_prologue && break_addr.IsValid()) { - const uint32_t prologue_byte_size = - sc.symbol->GetPrologueByteSize(); - if (prologue_byte_size) - break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); - else { - const Architecture *arch = - m_breakpoint->GetTarget().GetArchitecturePlugin(); - if (arch) - arch->AdjustBreakpointAddress(*sc.symbol, break_addr); - } - } - } + Address break_addr; + bool is_reexported; + std::tie(break_addr, is_reexported) = + ComputeBreakpointAddress(sc, m_skip_prologue); if (break_addr.IsValid()) { if (filter.AddressPasses(break_addr)) { @@ -396,6 +362,45 @@ return Searcher::eCallbackReturnContinue; } +std::tuple +BreakpointResolverName::ComputeBreakpointAddress(SymbolContext sc, + bool m_skip_prologue) { + bool is_reexported = false; + uint32_t prologue_byte_size = 0; + Address break_addr; + Architecture *arch = m_breakpoint->GetTarget().GetArchitecturePlugin(); + + if (sc.block && sc.block->GetInlinedFunctionInfo()) { + if (!sc.block->GetStartAddress(break_addr)) + break_addr.Clear(); + } else if (sc.function) { + break_addr = sc.function->GetAddressRange().GetBaseAddress(); + prologue_byte_size = sc.function->GetPrologueByteSize(); + } else if (sc.symbol) { + prologue_byte_size = sc.symbol->GetPrologueByteSize(); + if (sc.symbol->GetType() == eSymbolTypeReExported) { + const Symbol *actual_symbol = + sc.symbol->ResolveReExportedSymbol(m_breakpoint->GetTarget()); + if (actual_symbol) { + is_reexported = true; + break_addr = actual_symbol->GetAddress(); + } + } else { + break_addr = sc.symbol->GetAddress(); + } + } + + if (break_addr.IsValid()) { + if (prologue_byte_size && m_skip_prologue) { + break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); + } else if (arch) { + arch->AdjustBreakpointAddress(sc, break_addr); + } + } + + return std::make_tuple(break_addr, is_reexported); +} + lldb::SearchDepth BreakpointResolverName::GetDepth() { return lldb::eSearchDepthModule; } Index: source/Plugins/Architecture/PPC64/ArchitecturePPC64.h =================================================================== --- source/Plugins/Architecture/PPC64/ArchitecturePPC64.h +++ source/Plugins/Architecture/PPC64/ArchitecturePPC64.h @@ -31,7 +31,7 @@ //------------------------------------------------------------------ size_t GetBytesToSkip(Symbol &func, const Address &curr_addr) const override; - void AdjustBreakpointAddress(const Symbol &func, + void AdjustBreakpointAddress(const SymbolContext &sc, Address &addr) const override; private: Index: source/Plugins/Architecture/PPC64/ArchitecturePPC64.cpp =================================================================== --- source/Plugins/Architecture/PPC64/ArchitecturePPC64.cpp +++ source/Plugins/Architecture/PPC64/ArchitecturePPC64.cpp @@ -59,9 +59,12 @@ return 0; } -void ArchitecturePPC64::AdjustBreakpointAddress(const Symbol &func, +void ArchitecturePPC64::AdjustBreakpointAddress(const SymbolContext &sc, Address &addr) const { - int32_t loffs = GetLocalEntryOffset(func); + if (!sc.symbol) + return; + + int32_t loffs = GetLocalEntryOffset(*sc.symbol); if (!loffs) return;