diff options
Diffstat (limited to 'source/Plugins')
55 files changed, 1658 insertions, 897 deletions
diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp index 5073b13f09ab7..42acba232de1c 100644 --- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp +++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp @@ -334,11 +334,11 @@ ABIMacOSX_arm::GetArgumentValues (Thread &thread, size_t bit_width = 0; if (clang_type.IsIntegerType (is_signed)) { - bit_width = clang_type.GetBitSize(); + bit_width = clang_type.GetBitSize(nullptr); } else if (clang_type.IsPointerOrReferenceType ()) { - bit_width = clang_type.GetBitSize(); + bit_width = clang_type.GetBitSize(nullptr); } else { @@ -437,7 +437,7 @@ ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread, const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfoByName("r0", 0); if (clang_type.IsIntegerType (is_signed)) { - size_t bit_width = clang_type.GetBitSize(); + size_t bit_width = clang_type.GetBitSize(nullptr); switch (bit_width) { diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp index 465257db31d89..c2ba165afb4af 100644 --- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp +++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp @@ -322,11 +322,11 @@ ABIMacOSX_arm64::GetArgumentValues (Thread &thread, ValueList &values) const size_t bit_width = 0; if (value_type.IsIntegerType (is_signed)) { - bit_width = value_type.GetBitSize(); + bit_width = value_type.GetBitSize(nullptr); } else if (value_type.IsPointerOrReferenceType ()) { - bit_width = value_type.GetBitSize(); + bit_width = value_type.GetBitSize(nullptr); } else { @@ -709,7 +709,7 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx, uint32_t &NSRN, // NSRN (see ABI documentation) DataExtractor &data) { - const size_t byte_size = value_type.GetByteSize(); + const size_t byte_size = value_type.GetByteSize(nullptr); if (byte_size == 0) return false; @@ -728,7 +728,7 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx, { if (!base_type) return false; - const size_t base_byte_size = base_type.GetByteSize(); + const size_t base_byte_size = base_type.GetByteSize(nullptr); printf ("ClangASTContext::IsHomogeneousAggregate() => base_byte_size = %" PRIu64 "\n", (uint64_t) base_byte_size); uint32_t data_offset = 0; @@ -871,7 +871,7 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_ if (!reg_ctx) return return_valobj_sp; - const size_t byte_size = return_clang_type.GetByteSize(); + const size_t byte_size = return_clang_type.GetByteSize(nullptr); const uint32_t type_flags = return_clang_type.GetTypeInfo (NULL); if (type_flags & eTypeIsScalar || diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp index 9a1ea11cbae7e..ee5b9298721b5 100644 --- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp +++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp @@ -552,7 +552,7 @@ ABIMacOSX_i386::GetArgumentValues (Thread &thread, if (clang_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(), + clang_type.GetBitSize(nullptr), is_signed, thread.GetProcess().get(), current_stack_argument); @@ -560,7 +560,7 @@ ABIMacOSX_i386::GetArgumentValues (Thread &thread, else if (clang_type.IsPointerType()) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(), + clang_type.GetBitSize(nullptr), false, thread.GetProcess().get(), current_stack_argument); @@ -672,7 +672,7 @@ ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread, if (clang_type.IsIntegerType (is_signed)) { - size_t bit_width = clang_type.GetBitSize(); + size_t bit_width = clang_type.GetBitSize(nullptr); unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB]; @@ -732,6 +732,10 @@ ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread, return return_valobj_sp; } +// This defines the CFA as esp+4 +// the saved pc is at CFA-4 (i.e. esp+0) +// The saved esp is CFA+0 + bool ABIMacOSX_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) { @@ -745,12 +749,18 @@ ABIMacOSX_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) row->SetCFARegister (sp_reg_num); row->SetCFAOffset (4); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false); + row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); unwind_plan.AppendRow (row); unwind_plan.SetSourceName ("i386 at-func-entry default"); unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); return true; } +// This defines the CFA as ebp+8 +// The saved pc is at CFA-4 (i.e. ebp+4) +// The saved ebp is at CFA-8 (i.e. ebp+0) +// The saved esp is CFA+0 + bool ABIMacOSX_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) { @@ -786,6 +796,11 @@ ABIMacOSX_i386::RegisterIsVolatile (const RegisterInfo *reg_info) } // v. http://developer.apple.com/library/mac/#documentation/developertools/Conceptual/LowLevelABI/130-IA-32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4 +// +// This document ("OS X ABI Function Call Guide", chapter "IA-32 Function Calling Conventions") +// says that the following registers on i386 are preserved aka non-volatile aka callee-saved: +// +// ebx, ebp, esi, edi, esp bool ABIMacOSX_i386::RegisterIsCalleeSaved (const RegisterInfo *reg_info) diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp index adb3313d1a306..741afebfcb8b3 100644 --- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp +++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp @@ -444,7 +444,7 @@ ABISysV_ppc::GetArgumentValues (Thread &thread, if (clang_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(), + clang_type.GetBitSize(nullptr), is_signed, thread, argument_register_ids, @@ -454,7 +454,7 @@ ABISysV_ppc::GetArgumentValues (Thread &thread, else if (clang_type.IsPointerType ()) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(), + clang_type.GetBitSize(nullptr), false, thread, argument_register_ids, @@ -524,7 +524,7 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec error.SetErrorString ("We don't support returning complex values at present"); else { - size_t bit_width = clang_type.GetBitSize(); + size_t bit_width = clang_type.GetBitSize(nullptr); if (bit_width <= 64) { DataExtractor data; @@ -588,7 +588,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, { // Extract the register context so we can read arguments from registers - const size_t byte_size = return_clang_type.GetByteSize(); + const size_t byte_size = return_clang_type.GetByteSize(nullptr); uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0); const bool is_signed = (type_flags & eTypeIsSigned) != 0; switch (byte_size) @@ -637,7 +637,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, } else { - const size_t byte_size = return_clang_type.GetByteSize(); + const size_t byte_size = return_clang_type.GetByteSize(nullptr); if (byte_size <= sizeof(long double)) { const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); @@ -681,13 +681,11 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, } else if (type_flags & eTypeIsVector) { - const size_t byte_size = return_clang_type.GetByteSize(); + const size_t byte_size = return_clang_type.GetByteSize(nullptr); if (byte_size > 0) { - const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v0", 0); - if (altivec_reg == NULL) - altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0); + const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v2", 0); if (altivec_reg) { if (byte_size <= altivec_reg->byte_size) @@ -742,7 +740,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan if (!reg_ctx_sp) return return_valobj_sp; - const size_t bit_width = return_clang_type.GetBitSize(); + const size_t bit_width = return_clang_type.GetBitSize(nullptr); if (return_clang_type.IsAggregateType()) { Target *target = exe_ctx.GetTargetPtr(); @@ -784,7 +782,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan uint32_t count; ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); - const size_t field_bit_width = field_clang_type.GetBitSize(); + const size_t field_bit_width = field_clang_type.GetBitSize(nullptr); // If there are any unaligned fields, this is stored in memory. if (field_bit_offset % field_bit_width != 0) diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp index 46f1e1023f0a1..88c18fb6f2022 100644 --- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp +++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp @@ -444,7 +444,7 @@ ABISysV_ppc64::GetArgumentValues (Thread &thread, if (clang_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(), + clang_type.GetBitSize(nullptr), is_signed, thread, argument_register_ids, @@ -454,7 +454,7 @@ ABISysV_ppc64::GetArgumentValues (Thread &thread, else if (clang_type.IsPointerType ()) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(), + clang_type.GetBitSize(nullptr), false, thread, argument_register_ids, @@ -524,7 +524,7 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj error.SetErrorString ("We don't support returning complex values at present"); else { - size_t bit_width = clang_type.GetBitSize(); + size_t bit_width = clang_type.GetBitSize(nullptr); if (bit_width <= 64) { DataExtractor data; @@ -588,7 +588,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, { // Extract the register context so we can read arguments from registers - const size_t byte_size = return_clang_type.GetByteSize(); + const size_t byte_size = return_clang_type.GetByteSize(nullptr); uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0); const bool is_signed = (type_flags & eTypeIsSigned) != 0; switch (byte_size) @@ -637,7 +637,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, } else { - const size_t byte_size = return_clang_type.GetByteSize(); + const size_t byte_size = return_clang_type.GetByteSize(nullptr); if (byte_size <= sizeof(long double)) { const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); @@ -681,13 +681,11 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, } else if (type_flags & eTypeIsVector) { - const size_t byte_size = return_clang_type.GetByteSize(); + const size_t byte_size = return_clang_type.GetByteSize(nullptr); if (byte_size > 0) { - const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v0", 0); - if (altivec_reg == NULL) - altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0); + const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v2", 0); if (altivec_reg) { if (byte_size <= altivec_reg->byte_size) @@ -742,7 +740,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl if (!reg_ctx_sp) return return_valobj_sp; - const size_t bit_width = return_clang_type.GetBitSize(); + const size_t bit_width = return_clang_type.GetBitSize(nullptr); if (return_clang_type.IsAggregateType()) { Target *target = exe_ctx.GetTargetPtr(); @@ -784,7 +782,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl uint32_t count; ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); - const size_t field_bit_width = field_clang_type.GetBitSize(); + const size_t field_bit_width = field_clang_type.GetBitSize(nullptr); // If there are any unaligned fields, this is stored in memory. if (field_bit_offset % field_bit_width != 0) diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp index 776e7fea67c76..71d99c8c65d25 100644 --- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp +++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp @@ -510,7 +510,7 @@ ABISysV_x86_64::GetArgumentValues (Thread &thread, if (clang_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(), + clang_type.GetBitSize(nullptr), is_signed, thread, argument_register_ids, @@ -520,7 +520,7 @@ ABISysV_x86_64::GetArgumentValues (Thread &thread, else if (clang_type.IsPointerType ()) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(), + clang_type.GetBitSize(nullptr), false, thread, argument_register_ids, @@ -590,7 +590,7 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb error.SetErrorString ("We don't support returning complex values at present"); else { - size_t bit_width = clang_type.GetBitSize(); + size_t bit_width = clang_type.GetBitSize(nullptr); if (bit_width <= 64) { const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0); @@ -658,7 +658,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, { // Extract the register context so we can read arguments from registers - const size_t byte_size = return_clang_type.GetByteSize(); + const size_t byte_size = return_clang_type.GetByteSize(nullptr); uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("rax", 0), 0); const bool is_signed = (type_flags & eTypeIsSigned) != 0; switch (byte_size) @@ -707,7 +707,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, } else { - const size_t byte_size = return_clang_type.GetByteSize(); + const size_t byte_size = return_clang_type.GetByteSize(nullptr); if (byte_size <= sizeof(long double)) { const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0); @@ -755,7 +755,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, } else if (type_flags & eTypeIsVector) { - const size_t byte_size = return_clang_type.GetByteSize(); + const size_t byte_size = return_clang_type.GetByteSize(nullptr); if (byte_size > 0) { @@ -821,7 +821,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c if (!reg_ctx_sp) return return_valobj_sp; - const size_t bit_width = return_clang_type.GetBitSize(); + const size_t bit_width = return_clang_type.GetBitSize(nullptr); if (return_clang_type.IsAggregateType()) { Target *target = exe_ctx.GetTargetPtr(); @@ -869,7 +869,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c uint32_t count; ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); - const size_t field_bit_width = field_clang_type.GetBitSize(); + const size_t field_bit_width = field_clang_type.GetBitSize(nullptr); // If there are any unaligned fields, this is stored in memory. if (field_bit_offset % field_bit_width != 0) @@ -1070,6 +1070,10 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c return return_valobj_sp; } +// This defines the CFA as rsp+8 +// the saved pc is at CFA-8 (i.e. rsp+0) +// The saved rsp is CFA+0 + bool ABISysV_x86_64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) { @@ -1083,12 +1087,18 @@ ABISysV_x86_64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) row->SetCFARegister (sp_reg_num); row->SetCFAOffset (8); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -8, false); + row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); unwind_plan.AppendRow (row); unwind_plan.SetSourceName ("x86_64 at-func-entry default"); unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); return true; } +// This defines the CFA as rbp+16 +// The saved pc is at CFA-8 (i.e. rbp+8) +// The saved rbp is at CFA-16 (i.e. rbp+0) +// The saved rsp is CFA+0 + bool ABISysV_x86_64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) { @@ -1132,6 +1142,7 @@ ABISysV_x86_64::RegisterIsVolatile (const RegisterInfo *reg_info) // (this doc is also commonly referred to as the x86-64/AMD64 psABI) // Edited by Michael Matz, Jan Hubicka, Andreas Jaeger, and Mark Mitchell // current version is 0.99.6 released 2012-07-02 at http://refspecs.linuxfoundation.org/elf/x86-64-abi-0.99.pdf +// It's being revised & updated at https://github.com/hjl-tools/x86-psABI/ bool ABISysV_x86_64::RegisterIsCalleeSaved (const RegisterInfo *reg_info) diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp index 97ddbef0e3074..2f9012222c029 100644 --- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp +++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp @@ -371,7 +371,7 @@ public: } } - static RegularExpression s_regex("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?", REG_EXTENDED); + static RegularExpression s_regex("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?"); RegularExpression::Match matches(3); @@ -457,7 +457,7 @@ DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, uns std::unique_ptr<llvm::MCSymbolizer> symbolizer_up(curr_target->createMCSymbolizer(triple, NULL, DisassemblerLLVMC::SymbolLookupCallback, (void *) &owner, - m_context_ap.get(), RelInfo.release())); + m_context_ap.get(), std::move(RelInfo))); m_disasm_ap->setSymbolizer(std::move(symbolizer_up)); diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp index d8279e44e14ab..a504e801daac4 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp @@ -19,6 +19,8 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "llvm/Support/Path.h" + #include "DYLDRendezvous.h" using namespace lldb; @@ -238,9 +240,7 @@ DYLDRendezvous::UpdateSOEntriesForAddition() return false; // Only add shared libraries and not the executable. - // On Linux this is indicated by an empty path in the entry. - // On FreeBSD it is the name of the executable. - if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0) + if (SOEntryIsMainExecutable(entry)) continue; pos = std::find(m_soentries.begin(), m_soentries.end(), entry); @@ -277,6 +277,28 @@ DYLDRendezvous::UpdateSOEntriesForDeletion() } bool +DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry) +{ + // On Linux the executable is indicated by an empty path in the entry. On + // FreeBSD it is the full path to the executable. On Android, it is the + // basename of the executable. + + auto triple = m_process->GetTarget().GetArchitecture().GetTriple(); + auto os_type = triple.getOS(); + auto env_type = triple.getEnvironment(); + + switch (os_type) { + case llvm::Triple::FreeBSD: + return ::strcmp(entry.path.c_str(), m_exe_path) == 0; + case llvm::Triple::Linux: + return entry.path.empty() || (env_type == llvm::Triple::Android && + llvm::sys::path::filename(m_exe_path) == entry.path); + default: + return false; + } +} + +bool DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) { SOEntry entry; @@ -290,9 +312,7 @@ DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) return false; // Only add shared libraries and not the executable. - // On Linux this is indicated by an empty path in the entry. - // On FreeBSD it is the name of the executable. - if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0) + if (SOEntryIsMainExecutable(entry)) continue; entry_list.push_back(entry); diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h index ca00893179989..51fcd9b7d397d 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h @@ -247,6 +247,9 @@ protected: bool UpdateSOEntriesForDeletion(); + bool + SOEntryIsMainExecutable(const SOEntry &entry); + /// Reads the current list of shared objects according to the link map /// supplied by the runtime linker. bool diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index 6b0b6f5cc8b82..fdef1026f3c68 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -542,6 +542,9 @@ DynamicLoaderPOSIXDYLD::ComputeLoadOffset() return LLDB_INVALID_ADDRESS; ObjectFile *exe = module->GetObjectFile(); + if (!exe) + return LLDB_INVALID_ADDRESS; + Address file_entry = exe->GetEntryPointAddress(); if (!file_entry.IsValid()) diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index a6c74f3f1fc40..50537eb119f29 100644 --- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -291,7 +291,8 @@ ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType // the Itanium ABI. if (language == eLanguageTypeC_plus_plus || language == eLanguageTypeC_plus_plus_03 || - language == eLanguageTypeC_plus_plus_11) + language == eLanguageTypeC_plus_plus_11 || + language == eLanguageTypeC_plus_plus_14) return new ItaniumABILanguageRuntime (process); else return NULL; diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp index b1be0f5b1fe12..5b72728c2b482 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -288,82 +288,6 @@ PlatformPOSIX::PutFile (const lldb_private::FileSpec& source, } // if we are still here rsync has failed - let's try the slow way before giving up } - - if (log) - log->Printf ("PlatformPOSIX::PutFile(src='%s', dst='%s', uid=%u, gid=%u)", - source.GetPath().c_str(), - destination.GetPath().c_str(), - uid, - gid); // REMOVE THIS PRINTF PRIOR TO CHECKIN - // open - // read, write, read, write, ... - // close - // chown uid:gid dst - if (log) - log->Printf("[PutFile] Using block by block transfer....\n"); - - uint32_t source_open_options = File::eOpenOptionRead; - if (source.GetFileType() == FileSpec::eFileTypeSymbolicLink) - source_open_options |= File::eOpenoptionDontFollowSymlinks; - - File source_file(source, source_open_options, lldb::eFilePermissionsUserRW); - Error error; - uint32_t permissions = source_file.GetPermissions(error); - if (permissions == 0) - permissions = lldb::eFilePermissionsFileDefault; - - if (!source_file.IsValid()) - return Error("unable to open source file"); - lldb::user_id_t dest_file = OpenFile (destination, - File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate, - permissions, - error); - if (log) - log->Printf ("dest_file = %" PRIu64 "\n", dest_file); - if (error.Fail()) - return error; - if (dest_file == UINT64_MAX) - return Error("unable to open target file"); - lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0)); - uint64_t offset = 0; - while (error.Success()) - { - size_t bytes_read = buffer_sp->GetByteSize(); - error = source_file.Read(buffer_sp->GetBytes(), bytes_read); - if (bytes_read) - { - const uint64_t bytes_written = WriteFile(dest_file, offset, buffer_sp->GetBytes(), bytes_read, error); - offset += bytes_written; - if (bytes_written != bytes_read) - { - // We didn't write the correct numbe of bytes, so adjust - // the file position in the source file we are reading from... - source_file.SeekFromStart(offset); - } - } - else - break; - } - CloseFile(dest_file, error); - if (uid == UINT32_MAX && gid == UINT32_MAX) - return error; - // This is remopve, don't chown a local file... -// std::string dst_path (destination.GetPath()); -// if (chown_file(this,dst_path.c_str(),uid,gid) != 0) -// return Error("unable to perform chown"); - - - uint64_t src_md5[2]; - uint64_t dst_md5[2]; - - if (FileSystem::CalculateMD5 (source, src_md5[0], src_md5[1]) && CalculateMD5 (destination, dst_md5[0], dst_md5[1])) - { - if (src_md5[0] != dst_md5[0] || src_md5[1] != dst_md5[1]) - { - error.SetErrorString("md5 checksum of installed file doesn't match, installation failed"); - } - } - return error; } return Platform::PutFile(source,destination,uid,gid); } @@ -841,8 +765,12 @@ PlatformPOSIX::Attach (ProcessAttachInfo &attach_info, // Set UnixSignals appropriately. process_sp->SetUnixSignals (Host::GetUnixSignals ()); - ListenerSP listener_sp (new Listener("lldb.PlatformPOSIX.attach.hijack")); - attach_info.SetHijackListener(listener_sp); + auto listener_sp = attach_info.GetHijackListener(); + if (listener_sp == nullptr) + { + listener_sp.reset(new Listener("lldb.PlatformPOSIX.attach.hijack")); + attach_info.SetHijackListener(listener_sp); + } process_sp->HijackProcessEvents(listener_sp.get()); error = process_sp->Attach (attach_info); } diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index 43eae4d906ece..ec2084aaf98c5 100644 --- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -30,6 +30,8 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "Utility/UriParser.h" + using namespace lldb; using namespace lldb_private; @@ -105,12 +107,76 @@ PlatformRemoteGDBServer::ResolveExecutable (const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp, const FileSpecList *module_search_paths_ptr) { + // copied from PlatformRemoteiOS + Error error; - //error.SetErrorString ("PlatformRemoteGDBServer::ResolveExecutable() is unimplemented"); - if (m_gdb_client.GetFileExists(module_spec.GetFileSpec())) - return error; - // TODO: get the remote end to somehow resolve this file - error.SetErrorString("file not found on remote end"); + // Nothing special to do here, just use the actual file and architecture + + ModuleSpec resolved_module_spec(module_spec); + + // Resolve any executable within an apk on Android? + //Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec()); + + if (resolved_module_spec.GetFileSpec().Exists()) + { + if (resolved_module_spec.GetArchitecture().IsValid() || resolved_module_spec.GetUUID().IsValid()) + { + error = ModuleList::GetSharedModule (resolved_module_spec, + exe_module_sp, + NULL, + NULL, + NULL); + + if (exe_module_sp && exe_module_sp->GetObjectFile()) + return error; + exe_module_sp.reset(); + } + // No valid architecture was specified or the exact arch wasn't + // found so ask the platform for the architectures that we should be + // using (in the correct order) and see if we can find a match that way + StreamString arch_names; + for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx) + { + error = ModuleList::GetSharedModule (resolved_module_spec, + exe_module_sp, + NULL, + NULL, + NULL); + // Did we find an executable using one of the + if (error.Success()) + { + if (exe_module_sp && exe_module_sp->GetObjectFile()) + break; + else + error.SetErrorToGenericError(); + } + + if (idx > 0) + arch_names.PutCString (", "); + arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName()); + } + + if (error.Fail() || !exe_module_sp) + { + if (resolved_module_spec.GetFileSpec().Readable()) + { + error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s", + resolved_module_spec.GetFileSpec().GetPath().c_str(), + GetPluginName().GetCString(), + arch_names.GetString().c_str()); + } + else + { + error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str()); + } + } + } + else + { + error.SetErrorStringWithFormat ("'%s' does not exist", + resolved_module_spec.GetFileSpec().GetPath().c_str()); + } + return error; } @@ -146,6 +212,15 @@ PlatformRemoteGDBServer::~PlatformRemoteGDBServer() bool PlatformRemoteGDBServer::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) { + ArchSpec remote_arch = m_gdb_client.GetSystemArchitecture(); + + // TODO: 64 bit systems should also advertize support for 32 bit arch + // unknown CPU, we just support the one arch + if (idx == 0) + { + arch = remote_arch; + return true; + } return false; } @@ -252,6 +327,17 @@ PlatformRemoteGDBServer::ConnectRemote (Args& args) { const char *url = args.GetArgumentAtIndex(0); m_gdb_client.SetConnection (new ConnectionFileDescriptor()); + + // we're going to reuse the hostname when we connect to the debugserver + std::string scheme; + int port; + std::string path; + if ( !UriParser::Parse(url, scheme, m_platform_hostname, port, path) ) + { + error.SetErrorString("invalid uri"); + return error; + } + const ConnectionStatus status = m_gdb_client.Connect(url, &error); if (status == eConnectionStatusSuccess) { @@ -344,14 +430,30 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); Error error; - lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; if (log) log->Printf ("PlatformRemoteGDBServer::%s() called", __FUNCTION__); - m_gdb_client.SetSTDIN ("/dev/null"); - m_gdb_client.SetSTDOUT ("/dev/null"); - m_gdb_client.SetSTDERR ("/dev/null"); + auto num_file_actions = launch_info.GetNumFileActions (); + for (decltype(num_file_actions) i = 0; i < num_file_actions; ++i) + { + const auto file_action = launch_info.GetFileActionAtIndex (i); + if (file_action->GetAction () != FileAction::eFileActionOpen) + continue; + switch(file_action->GetFD()) + { + case STDIN_FILENO: + m_gdb_client.SetSTDIN (file_action->GetPath()); + break; + case STDOUT_FILENO: + m_gdb_client.SetSTDOUT (file_action->GetPath()); + break; + case STDERR_FILENO: + m_gdb_client.SetSTDERR (file_action->GetPath()); + break; + } + } + m_gdb_client.SetDisableASLR (launch_info.GetFlags().Test (eLaunchFlagDisableASLR)); m_gdb_client.SetDetachOnError (launch_info.GetFlags().Test (eLaunchFlagDetachOnError)); @@ -389,7 +491,7 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info) std::string error_str; if (m_gdb_client.GetLaunchSuccess (error_str)) { - pid = m_gdb_client.GetCurrentProcessID (); + const auto pid = m_gdb_client.GetCurrentProcessID (false); if (pid != LLDB_INVALID_PROCESS_ID) { launch_info.SetProcessID (pid); @@ -400,7 +502,7 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info) { if (log) log->Printf ("PlatformRemoteGDBServer::%s() launch succeeded but we didn't get a valid process id back!", __FUNCTION__); - // FIXME isn't this an error condition? Do we need to set an error here? Check with Greg. + error.SetErrorString ("failed to get PID"); } } else @@ -417,6 +519,14 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info) return error; } +Error +PlatformRemoteGDBServer::KillProcess (const lldb::pid_t pid) +{ + if (!m_gdb_client.KillSpawnedProcess(pid)) + return Error("failed to kill remote spawned process"); + return Error(); +} + lldb::ProcessSP PlatformRemoteGDBServer::DebugProcess (lldb_private::ProcessLaunchInfo &launch_info, lldb_private::Debugger &debugger, @@ -483,7 +593,7 @@ PlatformRemoteGDBServer::DebugProcess (lldb_private::ProcessLaunchInfo &launch_i const int connect_url_len = ::snprintf (connect_url, sizeof(connect_url), "connect://%s:%u", - override_hostname ? override_hostname : GetHostname (), + override_hostname ? override_hostname : m_platform_hostname.c_str(), port + port_offset); assert (connect_url_len < (int)sizeof(connect_url)); error = process_sp->ConnectRemote (NULL, connect_url); @@ -576,13 +686,19 @@ PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info, const int connect_url_len = ::snprintf (connect_url, sizeof(connect_url), "connect://%s:%u", - override_hostname ? override_hostname : GetHostname (), + override_hostname ? override_hostname : m_platform_hostname.c_str(), port + port_offset); assert (connect_url_len < (int)sizeof(connect_url)); - error = process_sp->ConnectRemote (NULL, connect_url); + error = process_sp->ConnectRemote(nullptr, connect_url); if (error.Success()) + { + auto listener = attach_info.GetHijackListener(); + if (listener != nullptr) + process_sp->HijackProcessEvents(listener.get()); error = process_sp->Attach(attach_info); - else if (debugserver_pid != LLDB_INVALID_PROCESS_ID) + } + + if (error.Fail() && debugserver_pid != LLDB_INVALID_PROCESS_ID) { m_gdb_client.KillSpawnedProcess(debugserver_pid); } diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h index 90b16b8b8fa9f..a928c4695f79d 100644 --- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h +++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -86,7 +86,10 @@ public: virtual lldb_private::Error LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info); - + + virtual lldb_private::Error + KillProcess (const lldb::pid_t pid); + virtual lldb::ProcessSP DebugProcess (lldb_private::ProcessLaunchInfo &launch_info, lldb_private::Debugger &debugger, @@ -212,6 +215,7 @@ public: protected: GDBRemoteCommunicationClient m_gdb_client; std::string m_platform_description; // After we connect we can get a more complete description of what we are connected to + std::string m_platform_hostname; private: DISALLOW_COPY_AND_ASSIGN (PlatformRemoteGDBServer); diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp index 84e35ba22644b..b33f83303971a 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -30,7 +30,7 @@ #include "lldb/Target/RegisterContext.h" #include "lldb/Utility/PseudoTerminal.h" - +#include "Plugins/Process/POSIX/CrashReason.h" #include "POSIXThread.h" #include "ProcessFreeBSD.h" #include "ProcessPOSIXLog.h" @@ -994,6 +994,11 @@ ProcessMonitor::Launch(LaunchArgs *args) if (PTRACE(PT_TRACE_ME, 0, NULL, 0) < 0) exit(ePtraceFailed); + // terminal has already dupped the tty descriptors to stdin/out/err. + // This closes original fd from which they were copied (and avoids + // leaking descriptors to the debugged process. + terminal.CloseSlaveFileDescriptor(); + // Do not inherit setgid powers. if (setgid(getgid()) != 0) exit(eSetGidFailed); @@ -1306,27 +1311,14 @@ ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, if (log) log->Printf ("ProcessMonitor::%s() received signal %s", __FUNCTION__, monitor->m_process->GetUnixSignals().GetSignalAsCString (signo)); - if (signo == SIGSEGV) { - lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr); - ProcessMessage::CrashReason reason = GetCrashReasonForSIGSEGV(info); - return ProcessMessage::Crash(tid, reason, signo, fault_addr); - } - - if (signo == SIGILL) { - lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr); - ProcessMessage::CrashReason reason = GetCrashReasonForSIGILL(info); - return ProcessMessage::Crash(tid, reason, signo, fault_addr); - } - - if (signo == SIGFPE) { - lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr); - ProcessMessage::CrashReason reason = GetCrashReasonForSIGFPE(info); - return ProcessMessage::Crash(tid, reason, signo, fault_addr); - } - - if (signo == SIGBUS) { + switch (signo) + { + case SIGSEGV: + case SIGILL: + case SIGFPE: + case SIGBUS: lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr); - ProcessMessage::CrashReason reason = GetCrashReasonForSIGBUS(info); + const auto reason = GetCrashReason(*info); return ProcessMessage::Crash(tid, reason, signo, fault_addr); } @@ -1335,141 +1327,6 @@ ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, return ProcessMessage::Signal(tid, signo); } -ProcessMessage::CrashReason -ProcessMonitor::GetCrashReasonForSIGSEGV(const siginfo_t *info) -{ - ProcessMessage::CrashReason reason; - assert(info->si_signo == SIGSEGV); - - reason = ProcessMessage::eInvalidCrashReason; - - switch (info->si_code) - { - default: - assert(false && "unexpected si_code for SIGSEGV"); - break; - case SEGV_MAPERR: - reason = ProcessMessage::eInvalidAddress; - break; - case SEGV_ACCERR: - reason = ProcessMessage::ePrivilegedAddress; - break; - } - - return reason; -} - -ProcessMessage::CrashReason -ProcessMonitor::GetCrashReasonForSIGILL(const siginfo_t *info) -{ - ProcessMessage::CrashReason reason; - assert(info->si_signo == SIGILL); - - reason = ProcessMessage::eInvalidCrashReason; - - switch (info->si_code) - { - default: - assert(false && "unexpected si_code for SIGILL"); - break; - case ILL_ILLOPC: - reason = ProcessMessage::eIllegalOpcode; - break; - case ILL_ILLOPN: - reason = ProcessMessage::eIllegalOperand; - break; - case ILL_ILLADR: - reason = ProcessMessage::eIllegalAddressingMode; - break; - case ILL_ILLTRP: - reason = ProcessMessage::eIllegalTrap; - break; - case ILL_PRVOPC: - reason = ProcessMessage::ePrivilegedOpcode; - break; - case ILL_PRVREG: - reason = ProcessMessage::ePrivilegedRegister; - break; - case ILL_COPROC: - reason = ProcessMessage::eCoprocessorError; - break; - case ILL_BADSTK: - reason = ProcessMessage::eInternalStackError; - break; - } - - return reason; -} - -ProcessMessage::CrashReason -ProcessMonitor::GetCrashReasonForSIGFPE(const siginfo_t *info) -{ - ProcessMessage::CrashReason reason; - assert(info->si_signo == SIGFPE); - - reason = ProcessMessage::eInvalidCrashReason; - - switch (info->si_code) - { - default: - assert(false && "unexpected si_code for SIGFPE"); - break; - case FPE_INTDIV: - reason = ProcessMessage::eIntegerDivideByZero; - break; - case FPE_INTOVF: - reason = ProcessMessage::eIntegerOverflow; - break; - case FPE_FLTDIV: - reason = ProcessMessage::eFloatDivideByZero; - break; - case FPE_FLTOVF: - reason = ProcessMessage::eFloatOverflow; - break; - case FPE_FLTUND: - reason = ProcessMessage::eFloatUnderflow; - break; - case FPE_FLTRES: - reason = ProcessMessage::eFloatInexactResult; - break; - case FPE_FLTINV: - reason = ProcessMessage::eFloatInvalidOperation; - break; - case FPE_FLTSUB: - reason = ProcessMessage::eFloatSubscriptRange; - break; - } - - return reason; -} - -ProcessMessage::CrashReason -ProcessMonitor::GetCrashReasonForSIGBUS(const siginfo_t *info) -{ - ProcessMessage::CrashReason reason; - assert(info->si_signo == SIGBUS); - - reason = ProcessMessage::eInvalidCrashReason; - - switch (info->si_code) - { - default: - assert(false && "unexpected si_code for SIGBUS"); - break; - case BUS_ADRALN: - reason = ProcessMessage::eIllegalAlignment; - break; - case BUS_ADRERR: - reason = ProcessMessage::eIllegalAddress; - break; - case BUS_OBJERR: - reason = ProcessMessage::eHardwareError; - break; - } - - return reason; -} - void ProcessMonitor::ServeOperation(OperationArgs *args) { @@ -1706,7 +1563,10 @@ ProcessMonitor::DupDescriptor(const char *path, int fd, int flags) if (target_fd == -1) return false; - return (dup2(target_fd, fd) == -1) ? false : true; + if (dup2(target_fd, fd) == -1) + return false; + + return (close(target_fd) == -1) ? false : true; } void @@ -1727,11 +1587,10 @@ ProcessMonitor::StopMonitor() StopOpThread(); sem_destroy(&m_operation_pending); sem_destroy(&m_operation_done); - - // Note: ProcessPOSIX passes the m_terminal_fd file descriptor to - // Process::SetSTDIOFileDescriptor, which in turn transfers ownership of - // the descriptor to a ConnectionFileDescriptor object. Consequently - // even though still has the file descriptor, we shouldn't close it here. + if (m_terminal_fd >= 0) { + close(m_terminal_fd); + m_terminal_fd = -1; + } } // FIXME: On Linux, when a new thread is created, we receive to notifications, diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h index 935fd85ed37a6..4ae963c89a2f4 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.h +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h @@ -79,7 +79,8 @@ public: /// Reads from this file descriptor yield both the standard output and /// standard error of this debugee. Even if stderr and stdout were /// redirected on launch it may still happen that data is available on this - /// descriptor (if the inferior process opens /dev/tty, for example). + /// descriptor (if the inferior process opens /dev/tty, for example). This descriptor is + /// closed after a call to StopMonitor(). /// /// If this monitor was attached to an existing process this method returns /// -1. @@ -311,18 +312,6 @@ private: MonitorSignal(ProcessMonitor *monitor, const siginfo_t *info, lldb::pid_t pid); - static ProcessMessage::CrashReason - GetCrashReasonForSIGSEGV(const siginfo_t *info); - - static ProcessMessage::CrashReason - GetCrashReasonForSIGILL(const siginfo_t *info); - - static ProcessMessage::CrashReason - GetCrashReasonForSIGFPE(const siginfo_t *info); - - static ProcessMessage::CrashReason - GetCrashReasonForSIGBUS(const siginfo_t *info); - void DoOperation(Operation *op); diff --git a/source/Plugins/Process/POSIX/CrashReason.cpp b/source/Plugins/Process/POSIX/CrashReason.cpp new file mode 100644 index 0000000000000..4dd91a6f1de8e --- /dev/null +++ b/source/Plugins/Process/POSIX/CrashReason.cpp @@ -0,0 +1,315 @@ +//===-- CrashReason.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "CrashReason.h" + +#include <sstream> + +namespace { + +void +AppendFaultAddr (std::string& str, lldb::addr_t addr) +{ + std::stringstream ss; + ss << " (fault address: 0x" << std::hex << addr << ")"; + str += ss.str(); +} + +CrashReason +GetCrashReasonForSIGSEGV(const siginfo_t& info) +{ + assert(info.si_signo == SIGSEGV); + + switch (info.si_code) + { + case SI_KERNEL: + // Linux will occasionally send spurious SI_KERNEL codes. + // (this is poorly documented in sigaction) + // One way to get this is via unaligned SIMD loads. + return CrashReason::eInvalidAddress; // for lack of anything better + case SEGV_MAPERR: + return CrashReason::eInvalidAddress; + case SEGV_ACCERR: + return CrashReason::ePrivilegedAddress; + } + + assert(false && "unexpected si_code for SIGSEGV"); + return CrashReason::eInvalidCrashReason; +} + +CrashReason +GetCrashReasonForSIGILL(const siginfo_t& info) +{ + assert(info.si_signo == SIGILL); + + switch (info.si_code) + { + case ILL_ILLOPC: + return CrashReason::eIllegalOpcode; + case ILL_ILLOPN: + return CrashReason::eIllegalOperand; + case ILL_ILLADR: + return CrashReason::eIllegalAddressingMode; + case ILL_ILLTRP: + return CrashReason::eIllegalTrap; + case ILL_PRVOPC: + return CrashReason::ePrivilegedOpcode; + case ILL_PRVREG: + return CrashReason::ePrivilegedRegister; + case ILL_COPROC: + return CrashReason::eCoprocessorError; + case ILL_BADSTK: + return CrashReason::eInternalStackError; + } + + assert(false && "unexpected si_code for SIGILL"); + return CrashReason::eInvalidCrashReason; +} + +CrashReason +GetCrashReasonForSIGFPE(const siginfo_t& info) +{ + assert(info.si_signo == SIGFPE); + + switch (info.si_code) + { + case FPE_INTDIV: + return CrashReason::eIntegerDivideByZero; + case FPE_INTOVF: + return CrashReason::eIntegerOverflow; + case FPE_FLTDIV: + return CrashReason::eFloatDivideByZero; + case FPE_FLTOVF: + return CrashReason::eFloatOverflow; + case FPE_FLTUND: + return CrashReason::eFloatUnderflow; + case FPE_FLTRES: + return CrashReason::eFloatInexactResult; + case FPE_FLTINV: + return CrashReason::eFloatInvalidOperation; + case FPE_FLTSUB: + return CrashReason::eFloatSubscriptRange; + } + + assert(false && "unexpected si_code for SIGFPE"); + return CrashReason::eInvalidCrashReason; +} + +CrashReason +GetCrashReasonForSIGBUS(const siginfo_t& info) +{ + assert(info.si_signo == SIGBUS); + + switch (info.si_code) + { + case BUS_ADRALN: + return CrashReason::eIllegalAlignment; + case BUS_ADRERR: + return CrashReason::eIllegalAddress; + case BUS_OBJERR: + return CrashReason::eHardwareError; + } + + assert(false && "unexpected si_code for SIGBUS"); + return CrashReason::eInvalidCrashReason; +} + +} + +std::string +GetCrashReasonString (CrashReason reason, lldb::addr_t fault_addr) +{ + std::string str; + + switch (reason) + { + default: + assert(false && "invalid CrashReason"); + break; + + case CrashReason::eInvalidAddress: + str = "invalid address"; + AppendFaultAddr (str, fault_addr); + break; + case CrashReason::ePrivilegedAddress: + str = "address access protected"; + AppendFaultAddr (str, fault_addr); + break; + case CrashReason::eIllegalOpcode: + str = "illegal instruction"; + break; + case CrashReason::eIllegalOperand: + str = "illegal instruction operand"; + break; + case CrashReason::eIllegalAddressingMode: + str = "illegal addressing mode"; + break; + case CrashReason::eIllegalTrap: + str = "illegal trap"; + break; + case CrashReason::ePrivilegedOpcode: + str = "privileged instruction"; + break; + case CrashReason::ePrivilegedRegister: + str = "privileged register"; + break; + case CrashReason::eCoprocessorError: + str = "coprocessor error"; + break; + case CrashReason::eInternalStackError: + str = "internal stack error"; + break; + case CrashReason::eIllegalAlignment: + str = "illegal alignment"; + break; + case CrashReason::eIllegalAddress: + str = "illegal address"; + break; + case CrashReason::eHardwareError: + str = "hardware error"; + break; + case CrashReason::eIntegerDivideByZero: + str = "integer divide by zero"; + break; + case CrashReason::eIntegerOverflow: + str = "integer overflow"; + break; + case CrashReason::eFloatDivideByZero: + str = "floating point divide by zero"; + break; + case CrashReason::eFloatOverflow: + str = "floating point overflow"; + break; + case CrashReason::eFloatUnderflow: + str = "floating point underflow"; + break; + case CrashReason::eFloatInexactResult: + str = "inexact floating point result"; + break; + case CrashReason::eFloatInvalidOperation: + str = "invalid floating point operation"; + break; + case CrashReason::eFloatSubscriptRange: + str = "invalid floating point subscript range"; + break; + } + + return str; +} + +const char * +CrashReasonAsString (CrashReason reason) +{ +#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION + // Just return the code in ascii for integration builds. + chcar str[8]; + sprintf(str, "%d", reason); +#else + const char *str = nullptr; + + switch (reason) + { + case CrashReason::eInvalidCrashReason: + str = "eInvalidCrashReason"; + break; + + // SIGSEGV crash reasons. + case CrashReason::eInvalidAddress: + str = "eInvalidAddress"; + break; + case CrashReason::ePrivilegedAddress: + str = "ePrivilegedAddress"; + break; + + // SIGILL crash reasons. + case CrashReason::eIllegalOpcode: + str = "eIllegalOpcode"; + break; + case CrashReason::eIllegalOperand: + str = "eIllegalOperand"; + break; + case CrashReason::eIllegalAddressingMode: + str = "eIllegalAddressingMode"; + break; + case CrashReason::eIllegalTrap: + str = "eIllegalTrap"; + break; + case CrashReason::ePrivilegedOpcode: + str = "ePrivilegedOpcode"; + break; + case CrashReason::ePrivilegedRegister: + str = "ePrivilegedRegister"; + break; + case CrashReason::eCoprocessorError: + str = "eCoprocessorError"; + break; + case CrashReason::eInternalStackError: + str = "eInternalStackError"; + break; + + // SIGBUS crash reasons: + case CrashReason::eIllegalAlignment: + str = "eIllegalAlignment"; + break; + case CrashReason::eIllegalAddress: + str = "eIllegalAddress"; + break; + case CrashReason::eHardwareError: + str = "eHardwareError"; + break; + + // SIGFPE crash reasons: + case CrashReason::eIntegerDivideByZero: + str = "eIntegerDivideByZero"; + break; + case CrashReason::eIntegerOverflow: + str = "eIntegerOverflow"; + break; + case CrashReason::eFloatDivideByZero: + str = "eFloatDivideByZero"; + break; + case CrashReason::eFloatOverflow: + str = "eFloatOverflow"; + break; + case CrashReason::eFloatUnderflow: + str = "eFloatUnderflow"; + break; + case CrashReason::eFloatInexactResult: + str = "eFloatInexactResult"; + break; + case CrashReason::eFloatInvalidOperation: + str = "eFloatInvalidOperation"; + break; + case CrashReason::eFloatSubscriptRange: + str = "eFloatSubscriptRange"; + break; + } +#endif + + return str; +} + +CrashReason +GetCrashReason(const siginfo_t& info) +{ + switch(info.si_signo) + { + case SIGSEGV: + return GetCrashReasonForSIGSEGV(info); + case SIGBUS: + return GetCrashReasonForSIGBUS(info); + case SIGFPE: + return GetCrashReasonForSIGFPE(info); + case SIGILL: + return GetCrashReasonForSIGILL(info); + } + + assert(false && "unexpected signal"); + return CrashReason::eInvalidCrashReason; +} diff --git a/source/Plugins/Process/POSIX/CrashReason.h b/source/Plugins/Process/POSIX/CrashReason.h new file mode 100644 index 0000000000000..f6d9ba553e4a0 --- /dev/null +++ b/source/Plugins/Process/POSIX/CrashReason.h @@ -0,0 +1,62 @@ +//===-- CrashReason.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_CrashReason_H_ +#define liblldb_CrashReason_H_ + +#include "lldb/lldb-types.h" + +#include <signal.h> + +#include <string> + +enum class CrashReason +{ + eInvalidCrashReason, + + // SIGSEGV crash reasons. + eInvalidAddress, + ePrivilegedAddress, + + // SIGILL crash reasons. + eIllegalOpcode, + eIllegalOperand, + eIllegalAddressingMode, + eIllegalTrap, + ePrivilegedOpcode, + ePrivilegedRegister, + eCoprocessorError, + eInternalStackError, + + // SIGBUS crash reasons, + eIllegalAlignment, + eIllegalAddress, + eHardwareError, + + // SIGFPE crash reasons, + eIntegerDivideByZero, + eIntegerOverflow, + eFloatDivideByZero, + eFloatOverflow, + eFloatUnderflow, + eFloatInexactResult, + eFloatInvalidOperation, + eFloatSubscriptRange +}; + +std::string +GetCrashReasonString (CrashReason reason, lldb::addr_t fault_addr); + +const char * +CrashReasonAsString (CrashReason reason); + +CrashReason +GetCrashReason(const siginfo_t& info); + +#endif // #ifndef liblldb_CrashReason_H_ diff --git a/source/Plugins/Process/POSIX/POSIXStopInfo.cpp b/source/Plugins/Process/POSIX/POSIXStopInfo.cpp index 6e2c140682ba2..3b8cea737bcbd 100644 --- a/source/Plugins/Process/POSIX/POSIXStopInfo.cpp +++ b/source/Plugins/Process/POSIX/POSIXStopInfo.cpp @@ -45,6 +45,15 @@ POSIXLimboStopInfo::ShouldNotify(Event *event_ptr) //===----------------------------------------------------------------------===// // POSIXCrashStopInfo +POSIXCrashStopInfo::POSIXCrashStopInfo(POSIXThread &thread, + uint32_t status, + CrashReason reason, + lldb::addr_t fault_addr) + : POSIXStopInfo(thread, status) +{ + m_description = ::GetCrashReasonString(reason, fault_addr); +} + POSIXCrashStopInfo::~POSIXCrashStopInfo() { } lldb::StopReason @@ -53,12 +62,6 @@ POSIXCrashStopInfo::GetStopReason() const return lldb::eStopReasonException; } -const char * -POSIXCrashStopInfo::GetDescription() -{ - return ProcessMessage::GetCrashReasonString(m_crash_reason, m_fault_addr); -} - //===----------------------------------------------------------------------===// // POSIXNewThreadStopInfo diff --git a/source/Plugins/Process/POSIX/POSIXStopInfo.h b/source/Plugins/Process/POSIX/POSIXStopInfo.h index cbf309e535062..a1ee2ea685244 100644 --- a/source/Plugins/Process/POSIX/POSIXStopInfo.h +++ b/source/Plugins/Process/POSIX/POSIXStopInfo.h @@ -16,8 +16,10 @@ // Project includes #include "lldb/Target/StopInfo.h" +#include "CrashReason.h" #include "POSIXThread.h" -#include "ProcessMessage.h" + +#include <string> //===----------------------------------------------------------------------===// /// @class POSIXStopInfo @@ -69,25 +71,13 @@ class POSIXCrashStopInfo { public: POSIXCrashStopInfo(POSIXThread &thread, uint32_t status, - ProcessMessage::CrashReason reason, - lldb::addr_t fault_addr) - : POSIXStopInfo(thread, status), - m_crash_reason(reason), - m_fault_addr(fault_addr) - { } - + CrashReason reason, + lldb::addr_t fault_addr); ~POSIXCrashStopInfo(); lldb::StopReason GetStopReason() const; - - const char * - GetDescription(); - -private: - ProcessMessage::CrashReason m_crash_reason; - lldb::addr_t m_fault_addr; -}; +}; //===----------------------------------------------------------------------===// /// @class POSIXNewThreadStopInfo diff --git a/source/Plugins/Process/POSIX/ProcessMessage.cpp b/source/Plugins/Process/POSIX/ProcessMessage.cpp index 5c53627f9e0bd..02049a2af9531 100644 --- a/source/Plugins/Process/POSIX/ProcessMessage.cpp +++ b/source/Plugins/Process/POSIX/ProcessMessage.cpp @@ -9,205 +9,19 @@ #include "ProcessMessage.h" -#include <sstream> - using namespace lldb_private; -namespace { - -inline void AppendFaultAddr(std::string& str, lldb::addr_t addr) -{ - std::stringstream ss; - ss << " (fault address: 0x" << std::hex << addr << ")"; - str += ss.str(); -} - -} - -const char * -ProcessMessage::GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr) -{ - static std::string str; - - switch (reason) - { - default: - assert(false && "invalid CrashReason"); - break; - - case eInvalidAddress: - str = "invalid address"; - AppendFaultAddr(str, fault_addr); - break; - case ePrivilegedAddress: - str = "address access protected"; - AppendFaultAddr(str, fault_addr); - break; - case eIllegalOpcode: - str = "illegal instruction"; - break; - case eIllegalOperand: - str = "illegal instruction operand"; - break; - case eIllegalAddressingMode: - str = "illegal addressing mode"; - break; - case eIllegalTrap: - str = "illegal trap"; - break; - case ePrivilegedOpcode: - str = "privileged instruction"; - break; - case ePrivilegedRegister: - str = "privileged register"; - break; - case eCoprocessorError: - str = "coprocessor error"; - break; - case eInternalStackError: - str = "internal stack error"; - break; - case eIllegalAlignment: - str = "illegal alignment"; - break; - case eIllegalAddress: - str = "illegal address"; - break; - case eHardwareError: - str = "hardware error"; - break; - case eIntegerDivideByZero: - str = "integer divide by zero"; - break; - case eIntegerOverflow: - str = "integer overflow"; - break; - case eFloatDivideByZero: - str = "floating point divide by zero"; - break; - case eFloatOverflow: - str = "floating point overflow"; - break; - case eFloatUnderflow: - str = "floating point underflow"; - break; - case eFloatInexactResult: - str = "inexact floating point result"; - break; - case eFloatInvalidOperation: - str = "invalid floating point operation"; - break; - case eFloatSubscriptRange: - str = "invalid floating point subscript range"; - break; - } - - return str.c_str(); -} - -const char * -ProcessMessage::PrintCrashReason(CrashReason reason) -{ -#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION - // Just return the code in asci for integration builds. - chcar str[8]; - sprintf(str, "%d", reason); -#else - const char *str = NULL; - - switch (reason) - { - case eInvalidCrashReason: - str = "eInvalidCrashReason"; - break; - - // SIGSEGV crash reasons. - case eInvalidAddress: - str = "eInvalidAddress"; - break; - case ePrivilegedAddress: - str = "ePrivilegedAddress"; - break; - - // SIGILL crash reasons. - case eIllegalOpcode: - str = "eIllegalOpcode"; - break; - case eIllegalOperand: - str = "eIllegalOperand"; - break; - case eIllegalAddressingMode: - str = "eIllegalAddressingMode"; - break; - case eIllegalTrap: - str = "eIllegalTrap"; - break; - case ePrivilegedOpcode: - str = "ePrivilegedOpcode"; - break; - case ePrivilegedRegister: - str = "ePrivilegedRegister"; - break; - case eCoprocessorError: - str = "eCoprocessorError"; - break; - case eInternalStackError: - str = "eInternalStackError"; - break; - - // SIGBUS crash reasons: - case eIllegalAlignment: - str = "eIllegalAlignment"; - break; - case eIllegalAddress: - str = "eIllegalAddress"; - break; - case eHardwareError: - str = "eHardwareError"; - break; - - // SIGFPE crash reasons: - case eIntegerDivideByZero: - str = "eIntegerDivideByZero"; - break; - case eIntegerOverflow: - str = "eIntegerOverflow"; - break; - case eFloatDivideByZero: - str = "eFloatDivideByZero"; - break; - case eFloatOverflow: - str = "eFloatOverflow"; - break; - case eFloatUnderflow: - str = "eFloatUnderflow"; - break; - case eFloatInexactResult: - str = "eFloatInexactResult"; - break; - case eFloatInvalidOperation: - str = "eFloatInvalidOperation"; - break; - case eFloatSubscriptRange: - str = "eFloatSubscriptRange"; - break; - } -#endif - - return str; -} - const char * ProcessMessage::PrintCrashReason() const { - return PrintCrashReason(m_crash_reason); + return CrashReasonAsString(m_crash_reason); } const char * ProcessMessage::PrintKind(Kind kind) { #ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION - // Just return the code in asci for integration builds. + // Just return the code in ascii for integration builds. chcar str[8]; sprintf(str, "%d", reason); #else diff --git a/source/Plugins/Process/POSIX/ProcessMessage.h b/source/Plugins/Process/POSIX/ProcessMessage.h index 40462d0f0e13d..f932e9fff2789 100644 --- a/source/Plugins/Process/POSIX/ProcessMessage.h +++ b/source/Plugins/Process/POSIX/ProcessMessage.h @@ -10,7 +10,10 @@ #ifndef liblldb_ProcessMessage_H_ #define liblldb_ProcessMessage_H_ +#include "CrashReason.h" + #include <cassert> +#include <string> #include "lldb/lldb-defines.h" #include "lldb/lldb-types.h" @@ -36,44 +39,10 @@ public: eExecMessage }; - enum CrashReason - { - eInvalidCrashReason, - - // SIGSEGV crash reasons. - eInvalidAddress, - ePrivilegedAddress, - - // SIGILL crash reasons. - eIllegalOpcode, - eIllegalOperand, - eIllegalAddressingMode, - eIllegalTrap, - ePrivilegedOpcode, - ePrivilegedRegister, - eCoprocessorError, - eInternalStackError, - - // SIGBUS crash reasons, - eIllegalAlignment, - eIllegalAddress, - eHardwareError, - - // SIGFPE crash reasons, - eIntegerDivideByZero, - eIntegerOverflow, - eFloatDivideByZero, - eFloatOverflow, - eFloatUnderflow, - eFloatInexactResult, - eFloatInvalidOperation, - eFloatSubscriptRange - }; - ProcessMessage() : m_tid(LLDB_INVALID_PROCESS_ID), m_kind(eInvalidMessage), - m_crash_reason(eInvalidCrashReason), + m_crash_reason(CrashReason::eInvalidCrashReason), m_status(0), m_addr(0) { } @@ -175,15 +144,9 @@ public: return m_child_tid; } - static const char * - GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr); - const char * PrintCrashReason() const; - static const char * - PrintCrashReason(CrashReason reason); - const char * PrintKind() const; @@ -195,7 +158,7 @@ private: int status = 0, lldb::addr_t addr = 0) : m_tid(tid), m_kind(kind), - m_crash_reason(eInvalidCrashReason), + m_crash_reason(CrashReason::eInvalidCrashReason), m_status(status), m_addr(addr), m_child_tid(0) { } @@ -203,14 +166,14 @@ private: ProcessMessage(lldb::tid_t tid, Kind kind, lldb::tid_t child_tid) : m_tid(tid), m_kind(kind), - m_crash_reason(eInvalidCrashReason), + m_crash_reason(CrashReason::eInvalidCrashReason), m_status(0), m_addr(0), m_child_tid(child_tid) { } lldb::tid_t m_tid; Kind m_kind : 8; - CrashReason m_crash_reason : 8; + CrashReason m_crash_reason; int m_status; lldb::addr_t m_addr; lldb::tid_t m_child_tid; diff --git a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp index 0e5ab5a8d8b1e..882fac75c9a0d 100644 --- a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp +++ b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp @@ -252,7 +252,16 @@ ProcessPOSIX::DoLaunch (Module *module, if (!error.Success()) return error; - SetSTDIOFileDescriptor(m_monitor->GetTerminalFD()); + int terminal = m_monitor->GetTerminalFD(); + if (terminal >= 0) { + // The reader thread will close the file descriptor when done, so we pass it a copy. + int stdio = fcntl(terminal, F_DUPFD_CLOEXEC, 0); + if (stdio == -1) { + error.SetErrorToErrno(); + return error; + } + SetSTDIOFileDescriptor(stdio); + } SetID(m_monitor->GetPID()); return error; diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp index b542db4779db4..80e1c1984225a 100644 --- a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp @@ -38,14 +38,21 @@ RegisterContextPOSIXProcessMonitor_powerpc::GetMonitor() bool RegisterContextPOSIXProcessMonitor_powerpc::ReadGPR() { - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize()); + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize()); } bool RegisterContextPOSIXProcessMonitor_powerpc::ReadFPR() { - // XXX not yet implemented + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadFPR(m_thread.GetID(), &m_fpr_powerpc, sizeof(m_fpr_powerpc)); +} + +bool +RegisterContextPOSIXProcessMonitor_powerpc::ReadVMX() +{ + // XXX: Need a way to read/write process VMX registers with ptrace. return false; } @@ -59,7 +66,14 @@ RegisterContextPOSIXProcessMonitor_powerpc::WriteGPR() bool RegisterContextPOSIXProcessMonitor_powerpc::WriteFPR() { - // XXX not yet implemented + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteFPR(m_thread.GetID(), &m_fpr_powerpc, sizeof(m_fpr_powerpc)); +} + +bool +RegisterContextPOSIXProcessMonitor_powerpc::WriteVMX() +{ + // XXX: Need a way to read/write process VMX registers with ptrace. return false; } @@ -146,26 +160,15 @@ RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(const RegisterInfo *reg { if (!ReadFPR()) return false; + uint8_t *src = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset; + value.SetUInt64(*(uint64_t*)src); } - else + else if (IsGPR(reg)) { - uint32_t full_reg = reg; - bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); - - if (is_subreg) - { - // Read the full aligned 64-bit register. - full_reg = reg_info->invalidate_regs[0]; - } - - bool success = ReadRegister(full_reg, value); + bool success = ReadRegister(reg, value); if (success) { - // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right. - if (is_subreg && (reg_info->byte_offset & 0x1)) - value.SetUInt64(value.GetAsUInt64() >> 8); - // If our return byte size was greater than the return value reg size, then // use the type specified by reg_info rather than the uint64_t default if (value.GetByteSize() > reg_info->byte_size) @@ -183,7 +186,16 @@ RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(const RegisterInfo *re const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; if (IsGPR(reg)) + { return WriteRegister(reg, value); + } + else if (IsFPR(reg)) + { + assert (reg_info->byte_offset < sizeof(m_fpr_powerpc)); + uint8_t *dst = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset; + *(uint64_t *)dst = value.GetAsUInt64(); + return WriteFPR(); + } return false; } @@ -221,6 +233,9 @@ RegisterContextPOSIXProcessMonitor_powerpc::WriteAllRegisterValues(const DataBuf if (WriteGPR()) { src += GetGPRSize(); + ::memcpy (&m_fpr_powerpc, src, sizeof(m_fpr_powerpc)); + + success = WriteFPR(); } } } diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h index 92a3312855152..5c686df4836fa 100644 --- a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h @@ -23,17 +23,26 @@ public: protected: bool + IsVMX(); + + bool ReadGPR(); bool ReadFPR(); bool + ReadVMX(); + + bool WriteGPR(); bool WriteFPR(); + bool + WriteVMX(); + // lldb_private::RegisterContext bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp index 1088924bfeac9..25a195e11a03c 100644 --- a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -15,7 +15,7 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Interpreter/Args.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/StreamFile.h" #include "lldb/DataFormatters/FormatManager.h" @@ -158,8 +158,8 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict regex_match.GetMatchAtIndex(slice_cstr, 2, msbit_str) && regex_match.GetMatchAtIndex(slice_cstr, 3, lsbit_str)) { - const uint32_t msbit = Args::StringToUInt32(msbit_str.c_str(), UINT32_MAX); - const uint32_t lsbit = Args::StringToUInt32(lsbit_str.c_str(), UINT32_MAX); + const uint32_t msbit = StringConvert::ToUInt32(msbit_str.c_str(), UINT32_MAX); + const uint32_t lsbit = StringConvert::ToUInt32(lsbit_str.c_str(), UINT32_MAX); if (msbit != UINT32_MAX && lsbit != UINT32_MAX) { if (msbit > lsbit) diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp b/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp index 5170e6d2accb3..5133d6088bd38 100644 --- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp +++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp @@ -134,6 +134,45 @@ typedef struct _FPR uint64_t fpscr; } FPR; +typedef struct _VMX +{ + uint32_t v0[4]; + uint32_t v1[4]; + uint32_t v2[4]; + uint32_t v3[4]; + uint32_t v4[4]; + uint32_t v5[4]; + uint32_t v6[4]; + uint32_t v7[4]; + uint32_t v8[4]; + uint32_t v9[4]; + uint32_t v10[4]; + uint32_t v11[4]; + uint32_t v12[4]; + uint32_t v13[4]; + uint32_t v14[4]; + uint32_t v15[4]; + uint32_t v16[4]; + uint32_t v17[4]; + uint32_t v18[4]; + uint32_t v19[4]; + uint32_t v20[4]; + uint32_t v21[4]; + uint32_t v22[4]; + uint32_t v23[4]; + uint32_t v24[4]; + uint32_t v25[4]; + uint32_t v26[4]; + uint32_t v27[4]; + uint32_t v28[4]; + uint32_t v29[4]; + uint32_t v30[4]; + uint32_t v31[4]; + uint32_t pad[2]; + uint32_t vrsave; + uint32_t vscr; +} VMX; + //--------------------------------------------------------------------------- // Include RegisterInfos_powerpc to declare our g_register_infos_powerpc structure. //--------------------------------------------------------------------------- diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index f47d687702ecf..1b3a9491d1c80 100644 --- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -811,7 +811,7 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () if (m_frame_type == eTrapHandlerFrame && process) { m_fast_unwind_plan_sp.reset(); - unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (process->GetTarget(), m_current_offset_backed_up_one); + unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one); if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc) && unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes) { return unwind_plan_sp; @@ -826,7 +826,10 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () // But there is not. if (process && process->GetDynamicLoader() && process->GetDynamicLoader()->AlwaysRelyOnEHUnwindInfo (m_sym_ctx)) { - unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (process->GetTarget(), m_current_offset_backed_up_one); + // We must specifically call the GetEHFrameUnwindPlan() method here -- normally we would + // call GetUnwindPlanAtCallSite() -- because CallSite may return an unwind plan sourced from + // either eh_frame (that's what we intend) or compact unwind (this won't work) + unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one); if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc)) { UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan because the DynamicLoader suggested we prefer it", diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp index b9b9dca07be4e..b38d6cc60cac9 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp @@ -125,3 +125,8 @@ RegisterContextLinux_i386::GetRegisterCount () const return static_cast<uint32_t> (sizeof (g_register_infos_i386) / sizeof (g_register_infos_i386 [0])); } +uint32_t +RegisterContextLinux_i386::GetUserRegisterCount () const +{ + return static_cast<uint32_t> (k_num_user_registers_i386); +} diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_i386.h b/source/Plugins/Process/Utility/RegisterContextLinux_i386.h index f8b21fc8e87d4..cb71d7993e172 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_i386.h +++ b/source/Plugins/Process/Utility/RegisterContextLinux_i386.h @@ -26,6 +26,9 @@ public: uint32_t GetRegisterCount () const override; + + uint32_t + GetUserRegisterCount () const override; }; #endif diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp index 74f016bd744d1..5c93ebf88faa0 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp @@ -145,10 +145,26 @@ GetRegisterInfoCount (const ArchSpec &target_arch) } } +static uint32_t +GetUserRegisterInfoCount (const ArchSpec &target_arch) +{ + switch (target_arch.GetMachine()) + { + case llvm::Triple::x86: + return static_cast<uint32_t> (k_num_user_registers_i386); + case llvm::Triple::x86_64: + return static_cast<uint32_t> (k_num_user_registers_x86_64); + default: + assert(false && "Unhandled target architecture."); + return 0; + } +} + RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(const ArchSpec &target_arch) : lldb_private::RegisterInfoInterface(target_arch), m_register_info_p (GetRegisterInfoPtr (target_arch)), - m_register_info_count (GetRegisterInfoCount (target_arch)) + m_register_info_count (GetRegisterInfoCount (target_arch)), + m_user_register_count (GetUserRegisterInfoCount (target_arch)) { } @@ -169,3 +185,9 @@ RegisterContextLinux_x86_64::GetRegisterCount () const { return m_register_info_count; } + +uint32_t +RegisterContextLinux_x86_64::GetUserRegisterCount () const +{ + return m_user_register_count; +} diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h index 7b6828661c1e7..0cdfae9ac9438 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h +++ b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h @@ -27,9 +27,13 @@ public: uint32_t GetRegisterCount () const override; + uint32_t + GetUserRegisterCount () const override; + private: const lldb_private::RegisterInfo *m_register_info_p; uint32_t m_register_info_count; + uint32_t m_user_register_count; }; #endif diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp index a9477d583517f..828fb2571f798 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp @@ -106,10 +106,49 @@ uint32_t g_fpr_regnums[] = fpr_fpscr_powerpc, }; +static const +uint32_t g_vmx_regnums[] = +{ + vmx_v0_powerpc, + vmx_v1_powerpc, + vmx_v2_powerpc, + vmx_v3_powerpc, + vmx_v4_powerpc, + vmx_v5_powerpc, + vmx_v6_powerpc, + vmx_v7_powerpc, + vmx_v8_powerpc, + vmx_v9_powerpc, + vmx_v10_powerpc, + vmx_v11_powerpc, + vmx_v12_powerpc, + vmx_v13_powerpc, + vmx_v14_powerpc, + vmx_v15_powerpc, + vmx_v16_powerpc, + vmx_v17_powerpc, + vmx_v18_powerpc, + vmx_v19_powerpc, + vmx_v20_powerpc, + vmx_v21_powerpc, + vmx_v22_powerpc, + vmx_v23_powerpc, + vmx_v24_powerpc, + vmx_v25_powerpc, + vmx_v26_powerpc, + vmx_v27_powerpc, + vmx_v28_powerpc, + vmx_v29_powerpc, + vmx_v30_powerpc, + vmx_v31_powerpc, + vmx_vrsave_powerpc, + vmx_vscr_powerpc, +}; + // Number of register sets provided by this context. enum { - k_num_register_sets = 2 + k_num_register_sets = 3 }; static const RegisterSet @@ -117,20 +156,26 @@ g_reg_sets_powerpc[k_num_register_sets] = { { "General Purpose Registers", "gpr", k_num_gpr_registers_powerpc, g_gpr_regnums }, { "Floating Point Registers", "fpr", k_num_fpr_registers_powerpc, g_fpr_regnums }, + { "Altivec/VMX Registers", "vmx", k_num_vmx_registers_powerpc, g_vmx_regnums }, }; bool RegisterContextPOSIX_powerpc::IsGPR(unsigned reg) { - return reg <= k_num_gpr_registers_powerpc; // GPR's come first. + return (reg >= k_first_gpr_powerpc) && (reg <= k_last_gpr_powerpc); // GPR's come first. } bool RegisterContextPOSIX_powerpc::IsFPR(unsigned reg) { - // XXX return (reg >= k_first_fpr) && (reg <= k_last_fpr); } +bool +RegisterContextPOSIX_powerpc::IsVMX(unsigned reg) +{ + return (reg >= k_first_vmx) && (reg <= k_last_vmx); +} + RegisterContextPOSIX_powerpc::RegisterContextPOSIX_powerpc(Thread &thread, uint32_t concrete_frame_idx, RegisterInfoInterface *register_info) diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h index 3194c3968c989..c7a2451d7811c 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h @@ -97,9 +97,47 @@ enum fpr_fpscr_powerpc, k_last_fpr = fpr_fpscr_powerpc, + k_first_vmx, + vmx_v0_powerpc = k_first_vmx, + vmx_v1_powerpc, + vmx_v2_powerpc, + vmx_v3_powerpc, + vmx_v4_powerpc, + vmx_v5_powerpc, + vmx_v6_powerpc, + vmx_v7_powerpc, + vmx_v8_powerpc, + vmx_v9_powerpc, + vmx_v10_powerpc, + vmx_v11_powerpc, + vmx_v12_powerpc, + vmx_v13_powerpc, + vmx_v14_powerpc, + vmx_v15_powerpc, + vmx_v16_powerpc, + vmx_v17_powerpc, + vmx_v18_powerpc, + vmx_v19_powerpc, + vmx_v20_powerpc, + vmx_v21_powerpc, + vmx_v22_powerpc, + vmx_v23_powerpc, + vmx_v24_powerpc, + vmx_v25_powerpc, + vmx_v26_powerpc, + vmx_v27_powerpc, + vmx_v28_powerpc, + vmx_v29_powerpc, + vmx_v30_powerpc, + vmx_v31_powerpc, + vmx_vrsave_powerpc, + vmx_vscr_powerpc, + k_last_vmx = vmx_vscr_powerpc, + k_num_registers_powerpc, k_num_gpr_registers_powerpc = k_last_gpr_powerpc - k_first_gpr_powerpc + 1, k_num_fpr_registers_powerpc = k_last_fpr - k_first_fpr + 1, + k_num_vmx_registers_powerpc = k_last_vmx - k_first_vmx + 1, }; class RegisterContextPOSIX_powerpc @@ -147,6 +185,8 @@ public: protected: uint64_t m_gpr_powerpc[k_num_gpr_registers_powerpc]; // general purpose registers. + uint64_t m_fpr_powerpc[k_num_fpr_registers_powerpc]; // floating point registers. + uint32_t m_vmx_powerpc[k_num_vmx_registers_powerpc][4]; std::unique_ptr<lldb_private::RegisterInfoInterface> m_register_info_ap; // Register Info Interface (FreeBSD or Linux) // Determines if an extended register set is supported on the processor running the inferior process. @@ -162,12 +202,17 @@ protected: bool IsFPR(unsigned reg); + bool + IsVMX(unsigned reg); + lldb::ByteOrder GetByteOrder(); virtual bool ReadGPR() = 0; virtual bool ReadFPR() = 0; + virtual bool ReadVMX() = 0; virtual bool WriteGPR() = 0; virtual bool WriteFPR() = 0; + virtual bool WriteVMX() = 0; }; #endif // #ifndef liblldb_RegisterContextPOSIX_powerpc_H_ diff --git a/source/Plugins/Process/Utility/RegisterContext_powerpc.h b/source/Plugins/Process/Utility/RegisterContext_powerpc.h index cf54cc0c2145b..7438b88971b3e 100644 --- a/source/Plugins/Process/Utility/RegisterContext_powerpc.h +++ b/source/Plugins/Process/Utility/RegisterContext_powerpc.h @@ -79,10 +79,45 @@ enum gcc_dwarf_f31_powerpc, gcc_dwarf_cr_powerpc, gcc_dwarf_fpscr_powerpc, + gcc_dwarf_msr_powerpc, + gcc_dwarf_vscr_powerpc, gcc_dwarf_xer_powerpc = 101, gcc_dwarf_lr_powerpc = 108, gcc_dwarf_ctr_powerpc, gcc_dwarf_pc_powerpc, + gcc_dwarf_vrsave_powerpc = 356, + gcc_dwarf_v0_powerpc = 1124, + gcc_dwarf_v1_powerpc, + gcc_dwarf_v2_powerpc, + gcc_dwarf_v3_powerpc, + gcc_dwarf_v4_powerpc, + gcc_dwarf_v5_powerpc, + gcc_dwarf_v6_powerpc, + gcc_dwarf_v7_powerpc, + gcc_dwarf_v8_powerpc, + gcc_dwarf_v9_powerpc, + gcc_dwarf_v10_powerpc, + gcc_dwarf_v11_powerpc, + gcc_dwarf_v12_powerpc, + gcc_dwarf_v13_powerpc, + gcc_dwarf_v14_powerpc, + gcc_dwarf_v15_powerpc, + gcc_dwarf_v16_powerpc, + gcc_dwarf_v17_powerpc, + gcc_dwarf_v18_powerpc, + gcc_dwarf_v19_powerpc, + gcc_dwarf_v20_powerpc, + gcc_dwarf_v21_powerpc, + gcc_dwarf_v22_powerpc, + gcc_dwarf_v23_powerpc, + gcc_dwarf_v24_powerpc, + gcc_dwarf_v25_powerpc, + gcc_dwarf_v26_powerpc, + gcc_dwarf_v27_powerpc, + gcc_dwarf_v28_powerpc, + gcc_dwarf_v29_powerpc, + gcc_dwarf_v30_powerpc, + gcc_dwarf_v31_powerpc, }; // GDB Register numbers (eRegisterKindGDB) @@ -152,12 +187,46 @@ enum gdb_f29_powerpc, gdb_f30_powerpc, gdb_f31_powerpc, - gdb_cr_powerpc, - gdb_fpscr_powerpc, - gdb_xer_powerpc = 101, - gdb_lr_powerpc = 108, - gdb_ctr_powerpc, gdb_pc_powerpc, + gdb_cr_powerpc = 66, + gdb_lr_powerpc, + gdb_ctr_powerpc, + gdb_xer_powerpc, + gdb_fpscr_powerpc, + gdb_v0_powerpc = 106, + gdb_v1_powerpc, + gdb_v2_powerpc, + gdb_v3_powerpc, + gdb_v4_powerpc, + gdb_v5_powerpc, + gdb_v6_powerpc, + gdb_v7_powerpc, + gdb_v8_powerpc, + gdb_v9_powerpc, + gdb_v10_powerpc, + gdb_v11_powerpc, + gdb_v12_powerpc, + gdb_v13_powerpc, + gdb_v14_powerpc, + gdb_v15_powerpc, + gdb_v16_powerpc, + gdb_v17_powerpc, + gdb_v18_powerpc, + gdb_v19_powerpc, + gdb_v20_powerpc, + gdb_v21_powerpc, + gdb_v22_powerpc, + gdb_v23_powerpc, + gdb_v24_powerpc, + gdb_v25_powerpc, + gdb_v26_powerpc, + gdb_v27_powerpc, + gdb_v28_powerpc, + gdb_v29_powerpc, + gdb_v30_powerpc, + gdb_v31_powerpc, + gdb_vscr_powerpc, + gdb_vrsave_powerpc, }; #endif // liblldb_RegisterContext_powerpc_H_ diff --git a/source/Plugins/Process/Utility/RegisterInfoInterface.h b/source/Plugins/Process/Utility/RegisterInfoInterface.h index 382475f4523ad..94cb5cc791c6e 100644 --- a/source/Plugins/Process/Utility/RegisterInfoInterface.h +++ b/source/Plugins/Process/Utility/RegisterInfoInterface.h @@ -32,9 +32,20 @@ namespace lldb_private virtual const lldb_private::RegisterInfo * GetRegisterInfo () const = 0; + // Returns the number of registers including the user registers and the + // lldb internal registers also virtual uint32_t GetRegisterCount () const = 0; + // Returns the number of the user registers (excluding the registers + // kept for lldb internal use only). Subclasses should override it if + // they belongs to an architecture with lldb internal registers. + virtual uint32_t + GetUserRegisterCount () const + { + return GetRegisterCount(); + } + const lldb_private::ArchSpec& GetTargetArchitecture() const { return m_target_arch; } diff --git a/source/Plugins/Process/Utility/RegisterInfos_powerpc.h b/source/Plugins/Process/Utility/RegisterInfos_powerpc.h index 045426648105b..fe145e99588be 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_powerpc.h +++ b/source/Plugins/Process/Utility/RegisterInfos_powerpc.h @@ -14,6 +14,8 @@ (offsetof(GPR, regname)) #define FPR_OFFSET(regname) \ (offsetof(FPR, regname)) +#define VMX_OFFSET(regname) \ + (offsetof(VMX, regname)) #define GPR_SIZE(regname) \ (sizeof(((GPR*)NULL)->regname)) @@ -26,6 +28,9 @@ #define DEFINE_FPR(reg, lldb_kind) \ { #reg, NULL, 8, FPR_OFFSET(reg), eEncodingIEEE754, \ eFormatFloat, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, fpr_##reg##_powerpc }, NULL, NULL } +#define DEFINE_VMX(reg, lldb_kind) \ + { #reg, NULL, 16, VMX_OFFSET(reg), eEncodingVector, \ + eFormatVectorOfUInt32, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, vmx_##reg##_powerpc }, NULL, NULL } // General purpose registers. GCC, DWARF, Generic, GDB #define POWERPC_REGS \ @@ -98,7 +103,42 @@ DEFINE_FPR(f29, LLDB_INVALID_REGNUM), \ DEFINE_FPR(f30, LLDB_INVALID_REGNUM), \ DEFINE_FPR(f31, LLDB_INVALID_REGNUM), \ - { "fpscr", NULL, 8, FPR_OFFSET(fpscr), eEncodingUint, eFormatHex, { gcc_dwarf_fpscr_powerpc, gcc_dwarf_fpscr_powerpc, LLDB_INVALID_REGNUM, gdb_fpscr_powerpc, fpr_fpscr_powerpc }, NULL, NULL }, + { "fpscr", NULL, 8, FPR_OFFSET(fpscr), eEncodingUint, eFormatHex, { gcc_dwarf_fpscr_powerpc, gcc_dwarf_fpscr_powerpc, LLDB_INVALID_REGNUM, gdb_fpscr_powerpc, fpr_fpscr_powerpc }, NULL, NULL }, \ + DEFINE_VMX(v0, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v1, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v2, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v3, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v4, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v5, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v6, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v7, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v8, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v9, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v10, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v11, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v12, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v13, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v14, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v15, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v16, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v17, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v18, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v19, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v20, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v21, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v22, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v23, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v24, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v25, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v26, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v27, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v28, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v29, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v30, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v31, LLDB_INVALID_REGNUM), \ + { "vrsave", NULL, 4, VMX_OFFSET(vrsave), eEncodingUint, eFormatHex, { gcc_dwarf_vrsave_powerpc, gcc_dwarf_vrsave_powerpc, LLDB_INVALID_REGNUM, gdb_vrsave_powerpc, vmx_vrsave_powerpc }, NULL, NULL }, \ + { "vscr", NULL, 4, VMX_OFFSET(vscr), eEncodingUint, eFormatHex, { gcc_dwarf_vscr_powerpc, gcc_dwarf_vscr_powerpc, LLDB_INVALID_REGNUM, gdb_vscr_powerpc, vmx_vscr_powerpc }, NULL, NULL }, + static RegisterInfo g_register_infos_powerpc64[] = { diff --git a/source/Plugins/Process/Utility/lldb-x86-register-enums.h b/source/Plugins/Process/Utility/lldb-x86-register-enums.h index 99fca3005820c..63027b4451b8e 100644 --- a/source/Plugins/Process/Utility/lldb-x86-register-enums.h +++ b/source/Plugins/Process/Utility/lldb-x86-register-enums.h @@ -118,7 +118,8 @@ namespace lldb_private k_num_registers_i386, k_num_gpr_registers_i386 = k_last_gpr_i386 - k_first_gpr_i386 + 1, k_num_fpr_registers_i386 = k_last_fpr_i386 - k_first_fpr_i386 + 1, - k_num_avx_registers_i386 = k_last_avx_i386 - k_first_avx_i386 + 1 + k_num_avx_registers_i386 = k_last_avx_i386 - k_first_avx_i386 + 1, + k_num_user_registers_i386 = k_num_gpr_registers_i386 + k_num_fpr_registers_i386 + k_num_avx_registers_i386, }; //--------------------------------------------------------------------------- @@ -285,7 +286,8 @@ namespace lldb_private k_num_registers_x86_64, k_num_gpr_registers_x86_64 = k_last_gpr_x86_64 - k_first_gpr_x86_64 + 1, k_num_fpr_registers_x86_64 = k_last_fpr_x86_64 - k_first_fpr_x86_64 + 1, - k_num_avx_registers_x86_64 = k_last_avx_x86_64 - k_first_avx_x86_64 + 1 + k_num_avx_registers_x86_64 = k_last_avx_x86_64 - k_first_avx_x86_64 + 1, + k_num_user_registers_x86_64 = k_num_gpr_registers_x86_64 + k_num_fpr_registers_x86_64 + k_num_avx_registers_x86_64, }; } diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp index fb39d7318a5a5..ead959508d881 100644 --- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -412,7 +412,8 @@ enum { NT_FPREGSET, NT_PRPSINFO, NT_THRMISC = 7, - NT_PROCSTAT_AUXV = 16 + NT_PROCSTAT_AUXV = 16, + NT_PPC_VMX = 0x100 }; } @@ -538,6 +539,9 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader * // FIXME: FreeBSD sticks an int at the beginning of the note m_auxv = DataExtractor(segment_data, note_start + 4, note_size - 4); break; + case FREEBSD::NT_PPC_VMX: + thread_data->vregset = note_data; + break; default: break; } diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp index 15b1b44182d7e..d12df21a86646 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp @@ -18,7 +18,8 @@ using namespace lldb_private; RegisterContextCorePOSIX_powerpc::RegisterContextCorePOSIX_powerpc(Thread &thread, RegisterInfoInterface *register_info, const DataExtractor &gpregset, - const DataExtractor &fpregset) + const DataExtractor &fpregset, + const DataExtractor &vregset) : RegisterContextPOSIX_powerpc(thread, 0, register_info) { m_gpr_buffer.reset(new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); @@ -27,6 +28,9 @@ RegisterContextCorePOSIX_powerpc::RegisterContextCorePOSIX_powerpc(Thread &threa m_fpr_buffer.reset(new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize())); m_fpr.SetData(m_fpr_buffer); m_fpr.SetByteOrder(fpregset.GetByteOrder()); + m_vec_buffer.reset(new DataBufferHeap(vregset.GetDataStart(), vregset.GetByteSize())); + m_vec.SetData(m_vec_buffer); + m_vec.SetByteOrder(fpregset.GetByteOrder()); } RegisterContextCorePOSIX_powerpc::~RegisterContextCorePOSIX_powerpc() @@ -46,6 +50,12 @@ RegisterContextCorePOSIX_powerpc::ReadFPR() } bool +RegisterContextCorePOSIX_powerpc::ReadVMX() +{ + return true; +} + +bool RegisterContextCorePOSIX_powerpc::WriteGPR() { assert(0); @@ -60,16 +70,31 @@ RegisterContextCorePOSIX_powerpc::WriteFPR() } bool +RegisterContextCorePOSIX_powerpc::WriteVMX() +{ + assert(0); + return false; +} + +bool RegisterContextCorePOSIX_powerpc::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) { lldb::offset_t offset = reg_info->byte_offset; - if (reg_info->name[0] == 'f') { + if (IsFPR(reg_info->kinds[lldb::eRegisterKindLLDB])) { uint64_t v = m_fpr.GetMaxU64(&offset, reg_info->byte_size); if (offset == reg_info->byte_offset + reg_info->byte_size) { value = v; return true; } + } else if (IsVMX(reg_info->kinds[lldb::eRegisterKindLLDB])) { + uint32_t v[4]; + offset = m_vec.CopyData(offset, reg_info->byte_size, &v); + if (offset == reg_info->byte_size) + { + value.SetBytes(v, reg_info->byte_size, m_vec.GetByteOrder()); + return true; + } } else { uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); if (offset == reg_info->byte_offset + reg_info->byte_size) diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h index e6575581b3600..a3590601fa7e6 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h @@ -20,7 +20,8 @@ public: RegisterContextCorePOSIX_powerpc (lldb_private::Thread &thread, lldb_private::RegisterInfoInterface *register_info, const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset); + const lldb_private::DataExtractor &fpregset, + const lldb_private::DataExtractor &vregset); ~RegisterContextCorePOSIX_powerpc(); @@ -47,16 +48,24 @@ protected: ReadFPR(); bool + ReadVMX(); + + bool WriteGPR(); bool WriteFPR(); + bool + WriteVMX(); + private: lldb::DataBufferSP m_gpr_buffer; lldb::DataBufferSP m_fpr_buffer; + lldb::DataBufferSP m_vec_buffer; lldb_private::DataExtractor m_gpr; lldb_private::DataExtractor m_fpr; + lldb_private::DataExtractor m_vec; }; #endif // #ifndef liblldb_RegisterContextCorePOSIX_powerpc_H_ diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp index d62bcfcff6003..b16335fb8e1e7 100644 --- a/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -38,7 +38,8 @@ ThreadElfCore::ThreadElfCore (Process &process, tid_t tid, m_thread_reg_ctx_sp (), m_signo(td.signo), m_gpregset_data(td.gpregset), - m_fpregset_data(td.fpregset) + m_fpregset_data(td.fpregset), + m_vregset_data(td.vregset) { } @@ -148,7 +149,7 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame) break; case llvm::Triple::ppc: case llvm::Triple::ppc64: - m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc (*this, reg_interface, m_gpregset_data, m_fpregset_data)); + m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc (*this, reg_interface, m_gpregset_data, m_fpregset_data, m_vregset_data)); break; case llvm::Triple::x86: case llvm::Triple::x86_64: diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.h b/source/Plugins/Process/elf-core/ThreadElfCore.h index f1f00cf019b3a..50502c101daf9 100644 --- a/source/Plugins/Process/elf-core/ThreadElfCore.h +++ b/source/Plugins/Process/elf-core/ThreadElfCore.h @@ -111,6 +111,7 @@ struct ThreadData { lldb_private::DataExtractor gpregset; lldb_private::DataExtractor fpregset; + lldb_private::DataExtractor vregset; int signo; std::string name; }; @@ -170,6 +171,7 @@ protected: lldb_private::DataExtractor m_gpregset_data; lldb_private::DataExtractor m_fpregset_data; + lldb_private::DataExtractor m_vregset_data; virtual bool CalculateStopInfo(); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 919fa54051179..d633b3eaf34c4 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -26,9 +26,11 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Host/Pipe.h" #include "lldb/Host/Socket.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/TimeValue.h" #include "lldb/Target/Process.h" +#include "llvm/ADT/SmallString.h" // Project includes #include "ProcessGDBRemoteLog.h" @@ -756,13 +758,14 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, } // use native registers, not the GDB registers - debugserver_args.AppendArgument("--native-regs"); - // make debugserver run in its own session so signals generated by - // special terminal key sequences (^C) don't affect debugserver - debugserver_args.AppendArgument("--setsid"); + debugserver_args.AppendArgument("--native-regs"); - char named_pipe_path[PATH_MAX]; - named_pipe_path[0] = '\0'; + if (launch_info.GetLaunchInSeparateProcessGroup()) + { + debugserver_args.AppendArgument("--setsid"); + } + + llvm::SmallString<PATH_MAX> named_pipe_path; Pipe port_named_pipe; bool listen = false; @@ -776,25 +779,11 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, { // Binding to port zero, we need to figure out what port it ends up // using using a named pipe... - FileSpec tmpdir_file_spec; - if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) - { - tmpdir_file_spec.AppendPathComponent("debugserver-named-pipe.XXXXXX"); - strncpy(named_pipe_path, tmpdir_file_spec.GetPath().c_str(), sizeof(named_pipe_path)); - } - else - { - strncpy(named_pipe_path, "/tmp/debugserver-named-pipe.XXXXXX", sizeof(named_pipe_path)); - } - - if (::mktemp (named_pipe_path)) - { - error = port_named_pipe.CreateNew(named_pipe_path, false); - if (error.Fail()) - return error; - debugserver_args.AppendArgument("--named-pipe"); - debugserver_args.AppendArgument(named_pipe_path); - } + error = port_named_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path); + if (error.Fail()) + return error; + debugserver_args.AppendArgument("--named-pipe"); + debugserver_args.AppendArgument(named_pipe_path.c_str()); } else { @@ -874,7 +863,7 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, if (error.Success() && launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) { - if (named_pipe_path[0]) + if (named_pipe_path.size() > 0) { error = port_named_pipe.OpenAsReader(named_pipe_path, false); if (error.Success()) @@ -887,14 +876,14 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, if (error.Success()) { assert (num_bytes > 0 && port_cstr[num_bytes-1] == '\0'); - out_port = Args::StringToUInt32(port_cstr, 0); + out_port = StringConvert::ToUInt32(port_cstr, 0); if (log) log->Printf("GDBRemoteCommunication::%s() debugserver listens %u port", __FUNCTION__, out_port); } else { if (log) - log->Printf("GDBRemoteCommunication::%s() failed to read a port value from named pipe %s: %s", __FUNCTION__, named_pipe_path, error.AsCString()); + log->Printf("GDBRemoteCommunication::%s() failed to read a port value from named pipe %s: %s", __FUNCTION__, named_pipe_path.c_str(), error.AsCString()); } port_named_pipe.Close(); @@ -902,13 +891,13 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, else { if (log) - log->Printf("GDBRemoteCommunication::%s() failed to open named pipe %s for reading: %s", __FUNCTION__, named_pipe_path, error.AsCString()); + log->Printf("GDBRemoteCommunication::%s() failed to open named pipe %s for reading: %s", __FUNCTION__, named_pipe_path.c_str(), error.AsCString()); } const auto err = port_named_pipe.Delete(named_pipe_path); if (err.Fail()) { if (log) - log->Printf ("GDBRemoteCommunication::%s failed to delete pipe %s: %s", __FUNCTION__, named_pipe_path, err.AsCString()); + log->Printf ("GDBRemoteCommunication::%s failed to delete pipe %s: %s", __FUNCTION__, named_pipe_path.c_str(), err.AsCString()); } } else if (listen) diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index ac203a62788a1..ee2f3276513d7 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -27,6 +27,16 @@ #include "Utility/StringExtractorGDBRemote.h" +typedef enum +{ + eStoppointInvalid = -1, + eBreakpointSoftware = 0, + eBreakpointHardware, + eWatchpointWrite, + eWatchpointRead, + eWatchpointReadWrite +} GDBStoppointType; + class ProcessGDBRemote; class GDBRemoteCommunication : public lldb_private::Communication @@ -282,9 +292,8 @@ protected: ListenThread (lldb::thread_arg_t arg); private: - lldb_private::HostThread m_listen_thread; + lldb_private::HostThread m_listen_thread; std::string m_listen_url; - //------------------------------------------------------------------ // For GDBRemoteCommunication only diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 52750de5a25f0..0f99688fc8232 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -28,6 +28,7 @@ #include "lldb/Host/Endian.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Host/TimeValue.h" #include "lldb/Target/Target.h" @@ -1210,13 +1211,13 @@ GDBRemoteCommunicationClient::SendInterrupt } lldb::pid_t -GDBRemoteCommunicationClient::GetCurrentProcessID () +GDBRemoteCommunicationClient::GetCurrentProcessID (bool allow_lazy) { - if (m_curr_pid_is_valid == eLazyBoolYes) + if (allow_lazy && m_curr_pid_is_valid == eLazyBoolYes) return m_curr_pid; // First try to retrieve the pid via the qProcessInfo request. - GetCurrentProcessInfo (); + GetCurrentProcessInfo (allow_lazy); if (m_curr_pid_is_valid == eLazyBoolYes) { // We really got it. @@ -1559,7 +1560,7 @@ GDBRemoteCommunicationClient::GetGDBServerVersion() size_t dot_pos = value.find('.'); if (dot_pos != std::string::npos) value[dot_pos] = '\0'; - const uint32_t version = Args::StringToUInt32(value.c_str(), UINT32_MAX, 0); + const uint32_t version = StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0); if (version != UINT32_MAX) { success = true; @@ -1625,14 +1626,14 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force) if (name.compare("cputype") == 0) { // exception type in big endian hex - cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0); + cpu = StringConvert::ToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0); if (cpu != LLDB_INVALID_CPUTYPE) ++num_keys_decoded; } else if (name.compare("cpusubtype") == 0) { // exception count in big endian hex - sub = Args::StringToUInt32 (value.c_str(), 0, 0); + sub = StringConvert::ToUInt32 (value.c_str(), 0, 0); if (sub != 0) ++num_keys_decoded; } @@ -1700,7 +1701,7 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force) } else if (name.compare("ptrsize") == 0) { - pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0); + pointer_byte_size = StringConvert::ToUInt32 (value.c_str(), 0, 0); if (pointer_byte_size != 0) ++num_keys_decoded; } @@ -1725,7 +1726,7 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force) } else if (name.compare("default_packet_timeout") == 0) { - m_default_packet_timeout = Args::StringToUInt32(value.c_str(), 0); + m_default_packet_timeout = StringConvert::ToUInt32(value.c_str(), 0); if (m_default_packet_timeout > 0) { SetPacketTimeout(m_default_packet_timeout); @@ -1865,6 +1866,21 @@ GDBRemoteCommunicationClient::SendAttach return -1; } +int +GDBRemoteCommunicationClient::SendStdinNotification (const char* data, size_t data_len) +{ + StreamString packet; + packet.PutCString("I"); + packet.PutBytesAsRawHex8(data, data_len); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success) + { + return 0; + } + return response.GetError(); + +} + const lldb_private::ArchSpec & GDBRemoteCommunicationClient::GetHostArchitecture () { @@ -2006,13 +2022,13 @@ GDBRemoteCommunicationClient::GetMemoryRegionInfo (lldb::addr_t addr, { if (name.compare ("start") == 0) { - addr_value = Args::StringToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16, &success); + addr_value = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16, &success); if (success) region_info.GetRange().SetRangeBase(addr_value); } else if (name.compare ("size") == 0) { - addr_value = Args::StringToUInt64(value.c_str(), 0, 16, &success); + addr_value = StringConvert::ToUInt64(value.c_str(), 0, 16, &success); if (success) region_info.GetRange().SetByteSize (addr_value); } @@ -2107,7 +2123,7 @@ GDBRemoteCommunicationClient::GetWatchpointSupportInfo (uint32_t &num) { if (name.compare ("num") == 0) { - num = Args::StringToUInt32(value.c_str(), 0, 0); + num = StringConvert::ToUInt32(value.c_str(), 0, 0); m_num_supported_hardware_watchpoints = num; } } @@ -2309,27 +2325,27 @@ GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemot { if (name.compare("pid") == 0) { - process_info.SetProcessID (Args::StringToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0)); + process_info.SetProcessID (StringConvert::ToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0)); } else if (name.compare("ppid") == 0) { - process_info.SetParentProcessID (Args::StringToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0)); + process_info.SetParentProcessID (StringConvert::ToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0)); } else if (name.compare("uid") == 0) { - process_info.SetUserID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0)); + process_info.SetUserID (StringConvert::ToUInt32 (value.c_str(), UINT32_MAX, 0)); } else if (name.compare("euid") == 0) { - process_info.SetEffectiveUserID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0)); + process_info.SetEffectiveUserID (StringConvert::ToUInt32 (value.c_str(), UINT32_MAX, 0)); } else if (name.compare("gid") == 0) { - process_info.SetGroupID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0)); + process_info.SetGroupID (StringConvert::ToUInt32 (value.c_str(), UINT32_MAX, 0)); } else if (name.compare("egid") == 0) { - process_info.SetEffectiveGroupID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0)); + process_info.SetEffectiveGroupID (StringConvert::ToUInt32 (value.c_str(), UINT32_MAX, 0)); } else if (name.compare("triple") == 0) { @@ -2351,11 +2367,11 @@ GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemot } else if (name.compare("cputype") == 0) { - cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 16); + cpu = StringConvert::ToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 16); } else if (name.compare("cpusubtype") == 0) { - sub = Args::StringToUInt32 (value.c_str(), 0, 16); + sub = StringConvert::ToUInt32 (value.c_str(), 0, 16); } else if (name.compare("vendor") == 0) { @@ -2408,14 +2424,17 @@ GDBRemoteCommunicationClient::GetProcessInfo (lldb::pid_t pid, ProcessInstanceIn } bool -GDBRemoteCommunicationClient::GetCurrentProcessInfo () +GDBRemoteCommunicationClient::GetCurrentProcessInfo (bool allow_lazy) { Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); - if (m_qProcessInfo_is_valid == eLazyBoolYes) - return true; - if (m_qProcessInfo_is_valid == eLazyBoolNo) - return false; + if (allow_lazy) + { + if (m_qProcessInfo_is_valid == eLazyBoolYes) + return true; + if (m_qProcessInfo_is_valid == eLazyBoolNo) + return false; + } GetHostInfo (); @@ -2441,13 +2460,13 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo () { if (name.compare("cputype") == 0) { - cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 16); + cpu = StringConvert::ToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 16); if (cpu != LLDB_INVALID_CPUTYPE) ++num_keys_decoded; } else if (name.compare("cpusubtype") == 0) { - sub = Args::StringToUInt32 (value.c_str(), 0, 16); + sub = StringConvert::ToUInt32 (value.c_str(), 0, 16); if (sub != 0) ++num_keys_decoded; } @@ -2483,13 +2502,13 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo () } else if (name.compare("ptrsize") == 0) { - pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 16); + pointer_byte_size = StringConvert::ToUInt32 (value.c_str(), 0, 16); if (pointer_byte_size != 0) ++num_keys_decoded; } else if (name.compare("pid") == 0) { - pid = Args::StringToUInt64(value.c_str(), 0, 16); + pid = StringConvert::ToUInt64(value.c_str(), 0, 16); if (pid != LLDB_INVALID_PROCESS_ID) ++num_keys_decoded; } @@ -2849,7 +2868,11 @@ GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid, const const char *packet = stream.GetData(); int packet_len = stream.GetSize(); - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) + // give the process a few seconds to startup + const uint32_t old_packet_timeout = SetPacketTimeout (10); + auto result = SendPacketAndWaitForResponse(packet, packet_len, response, false); + SetPacketTimeout (old_packet_timeout); + if (result == PacketResult::Success) { std::string name; std::string value; @@ -2857,9 +2880,9 @@ GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid, const while (response.GetNameColonValue(name, value)) { if (name.compare("port") == 0) - port = Args::StringToUInt32(value.c_str(), 0, 0); + port = StringConvert::ToUInt32(value.c_str(), 0, 0); else if (name.compare("pid") == 0) - pid = Args::StringToUInt64(value.c_str(), LLDB_INVALID_PROCESS_ID, 0); + pid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_PROCESS_ID, 0); } return port; } @@ -3013,6 +3036,7 @@ GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type, case eWatchpointWrite: m_supports_z2 = false; break; case eWatchpointRead: m_supports_z3 = false; break; case eWatchpointReadWrite: m_supports_z4 = false; break; + case eStoppointInvalid: return UINT8_MAX; } } } diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index fddcd6cd14268..d90614bce88b2 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -21,15 +21,6 @@ #include "GDBRemoteCommunication.h" -typedef enum -{ - eBreakpointSoftware = 0, - eBreakpointHardware, - eWatchpointWrite, - eWatchpointRead, - eWatchpointReadWrite -} GDBStoppointType; - class GDBRemoteCommunicationClient : public GDBRemoteCommunication { public: @@ -109,7 +100,7 @@ public: bool &timed_out); lldb::pid_t - GetCurrentProcessID (); + GetCurrentProcessID (bool allow_lazy = true); bool GetLaunchSuccess (std::string &error_str); @@ -184,6 +175,23 @@ public: //------------------------------------------------------------------ + /// Sends a GDB remote protocol 'I' packet that delivers stdin + /// data to the remote process. + /// + /// @param[in] data + /// A pointer to stdin data. + /// + /// @param[in] data_len + /// The number of bytes available at \a data. + /// + /// @return + /// Zero if the attach was successful, or an error indicating + /// an error code. + //------------------------------------------------------------------ + int + SendStdinNotification(const char* data, size_t data_len); + + //------------------------------------------------------------------ /// Sets the path to use for stdin/out/err for a process /// that will be launched with the 'A' packet. /// @@ -375,8 +383,8 @@ public: case eWatchpointWrite: return m_supports_z2; case eWatchpointRead: return m_supports_z3; case eWatchpointReadWrite: return m_supports_z4; + case eStoppointInvalid: return false; } - return false; } uint8_t SendGDBStoppointTypePacket (GDBStoppointType type, // Type of breakpoint or watchpoint @@ -534,7 +542,7 @@ protected: StringExtractorGDBRemote &response); bool - GetCurrentProcessInfo (); + GetCurrentProcessInfo (bool allow_lazy_pid = true); bool GetGDBServerVersion(); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index a7149505e869e..dd920c0df0cab 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -34,16 +34,18 @@ #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Host/TimeValue.h" #include "lldb/Target/FileAction.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" -#include "lldb/Target/NativeRegisterContext.h" -#include "Host/common/NativeProcessProtocol.h" -#include "Host/common/NativeThreadProtocol.h" +#include "lldb/Host/common/NativeRegisterContext.h" +#include "lldb/Host/common/NativeProcessProtocol.h" +#include "lldb/Host/common/NativeThreadProtocol.h" // Project includes #include "Utility/StringExtractorGDBRemote.h" +#include "Utility/UriParser.h" #include "ProcessGDBRemote.h" #include "ProcessGDBRemoteLog.h" @@ -276,6 +278,10 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec, packet_result = Handle_qPlatform_shell (packet); break; + case StringExtractorGDBRemote::eServerPacketType_qWatchpointSupportInfo: + packet_result = Handle_qWatchpointSupportInfo (packet); + break; + case StringExtractorGDBRemote::eServerPacketType_C: packet_result = Handle_C (packet); break; @@ -364,6 +370,10 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec, packet_result = Handle_H (packet); break; + case StringExtractorGDBRemote::eServerPacketType_I: + packet_result = Handle_I (packet); + break; + case StringExtractorGDBRemote::eServerPacketType_m: packet_result = Handle_m (packet); break; @@ -601,14 +611,12 @@ GDBRemoteCommunicationServer::LaunchPlatformProcess () // add to list of spawned processes. On an lldb-gdbserver, we // would expect there to be only one. - lldb::pid_t pid; - if ( (pid = m_process_launch_info.GetProcessID()) != LLDB_INVALID_PROCESS_ID ) + const auto pid = m_process_launch_info.GetProcessID(); + if (pid != LLDB_INVALID_PROCESS_ID) { // add to spawned pids - { - Mutex::Locker locker (m_spawned_pids_mutex); - m_spawned_pids.insert(pid); - } + Mutex::Locker locker (m_spawned_pids_mutex); + m_spawned_pids.insert(pid); } return error; @@ -835,12 +843,12 @@ GDBRemoteCommunicationServer::SendStopReplyPacketForThread (lldb::tid_t tid) // Grab the reason this thread stopped. struct ThreadStopInfo tid_stop_info; - if (!thread_sp->GetStopReason (tid_stop_info)) + std::string description; + if (!thread_sp->GetStopReason (tid_stop_info, description)) return SendErrorResponse (52); - const bool did_exec = tid_stop_info.reason == eStopReasonExec; // FIXME implement register handling for exec'd inferiors. - // if (did_exec) + // if (tid_stop_info.reason == eStopReasonExec) // { // const bool force = true; // InitializeRegisters(force); @@ -861,25 +869,6 @@ GDBRemoteCommunicationServer::SendStopReplyPacketForThread (lldb::tid_t tid) tid_stop_info.details.exception.type); } - switch (tid_stop_info.reason) - { - case eStopReasonSignal: - case eStopReasonException: - signum = thread_sp->TranslateStopInfoToGdbSignal (tid_stop_info); - break; - default: - signum = 0; - if (log) - { - log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " tid %" PRIu64 " has stop reason %d, using signo = 0 in stop reply response", - __FUNCTION__, - m_debugged_process_sp->GetID (), - tid, - tid_stop_info.reason); - } - break; - } - // Print the signal number. response.PutHex8 (signum & 0xff); @@ -906,14 +895,6 @@ GDBRemoteCommunicationServer::SendStopReplyPacketForThread (lldb::tid_t tid) response.PutChar (';'); } - // FIXME look for analog - // thread_identifier_info_data_t thread_ident_info; - // if (DNBThreadGetIdentifierInfo (pid, tid, &thread_ident_info)) - // { - // if (thread_ident_info.dispatch_qaddr != 0) - // ostrm << std::hex << "qaddr:" << thread_ident_info.dispatch_qaddr << ';'; - // } - // If a 'QListThreadsInStopReply' was sent to enable this feature, we // will send all thread IDs back in the "threads" key whose value is // a list of hex thread IDs separated by commas: @@ -978,9 +959,45 @@ GDBRemoteCommunicationServer::SendStopReplyPacketForThread (lldb::tid_t tid) } } - if (did_exec) + const char* reason_str = nullptr; + switch (tid_stop_info.reason) + { + case eStopReasonTrace: + reason_str = "trace"; + break; + case eStopReasonBreakpoint: + reason_str = "breakpoint"; + break; + case eStopReasonWatchpoint: + reason_str = "watchpoint"; + break; + case eStopReasonSignal: + reason_str = "signal"; + break; + case eStopReasonException: + reason_str = "exception"; + break; + case eStopReasonExec: + reason_str = "exec"; + break; + case eStopReasonInstrumentation: + case eStopReasonInvalid: + case eStopReasonPlanComplete: + case eStopReasonThreadExiting: + case eStopReasonNone: + break; + } + if (reason_str != nullptr) + { + response.Printf ("reason:%s;", reason_str); + } + + if (!description.empty()) { - response.PutCString ("reason:exec;"); + // Description may contains special chars, send as hex bytes. + response.PutCString ("description:"); + response.PutCStringAsRawHex8 (description.c_str ()); + response.PutChar (';'); } else if ((tid_stop_info.reason == eStopReasonException) && tid_stop_info.details.exception.type) { @@ -1422,23 +1439,34 @@ CreateProcessInfoResponse_DebugServerStyle (const ProcessInstanceInfo &proc_info GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::Handle_qProcessInfo (StringExtractorGDBRemote &packet) { - // Only the gdb server handles this. - if (!IsGdbServer ()) - return SendUnimplementedResponse (packet.GetStringRef ().c_str ()); - - // Fail if we don't have a current process. - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - return SendErrorResponse (68); - - ProcessInstanceInfo proc_info; - if (Host::GetProcessInfo (m_debugged_process_sp->GetID (), proc_info)) + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; + + if (IsGdbServer ()) { - StreamString response; - CreateProcessInfoResponse_DebugServerStyle(proc_info, response); - return SendPacketNoLock (response.GetData (), response.GetSize ()); + // Fail if we don't have a current process. + if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse (68); + + pid = m_debugged_process_sp->GetID (); } - - return SendErrorResponse (1); + else if (m_is_platform) + { + pid = m_process_launch_info.GetProcessID (); + m_process_launch_info.Clear (); + } + else + return SendUnimplementedResponse (packet.GetStringRef ().c_str ()); + + if (pid == LLDB_INVALID_PROCESS_ID) + return SendErrorResponse (1); + + ProcessInstanceInfo proc_info; + if (!Host::GetProcessInfo (pid, proc_info)) + return SendErrorResponse (1); + + StreamString response; + CreateProcessInfoResponse_DebugServerStyle(proc_info, response); + return SendPacketNoLock (response.GetData (), response.GetSize ()); } GDBRemoteCommunication::PacketResult @@ -1512,27 +1540,27 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa } else if (key.compare("pid") == 0) { - match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); + match_info.GetProcessInfo().SetProcessID (StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); } else if (key.compare("parent_pid") == 0) { - match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); + match_info.GetProcessInfo().SetParentProcessID (StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); } else if (key.compare("uid") == 0) { - match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); + match_info.GetProcessInfo().SetUserID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success)); } else if (key.compare("gid") == 0) { - match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); + match_info.GetProcessInfo().SetGroupID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success)); } else if (key.compare("euid") == 0) { - match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); + match_info.GetProcessInfo().SetEffectiveUserID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success)); } else if (key.compare("egid") == 0) { - match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); + match_info.GetProcessInfo().SetEffectiveGroupID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success)); } else if (key.compare("all_users") == 0) { @@ -1627,7 +1655,7 @@ GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packe bool success = packet.GetNameColonValue(key, value); if (success && key.compare("response_size") == 0) { - uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success); + uint32_t response_size = StringConvert::ToUInt32(value.c_str(), 0, 0, &success); if (success) { if (response_size == 0) @@ -1901,7 +1929,7 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote if (name.compare ("host") == 0) hostname.swap(value); else if (name.compare ("port") == 0) - port = Args::StringToUInt32(value.c_str(), 0, 0); + port = StringConvert::ToUInt32(value.c_str(), 0, 0); } if (port == UINT16_MAX) port = GetNextAvailablePort(); @@ -1909,6 +1937,9 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote // Spawn a new thread to accept the port that gets bound after // binding to port 0 (zero). + // ignore the hostname send from the remote end, just use the ip address + // that we're currently communicating with as the hostname + // Spawn a debugserver and try to get the port it listens to. ProcessLaunchInfo debugserver_launch_info; if (hostname.empty()) @@ -1916,9 +1947,19 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote if (log) log->Printf("Launching debugserver with: %s:%u...\n", hostname.c_str(), port); + // Do not run in a new session so that it can not linger after the + // platform closes. + debugserver_launch_info.SetLaunchInSeparateProcessGroup(false); debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false); - Error error = StartDebugserverProcess (hostname.empty() ? NULL : hostname.c_str(), + std::string platform_scheme; + std::string platform_ip; + int platform_port; + std::string platform_path; + bool ok = UriParser::Parse(GetConnection()->GetURI().c_str(), platform_scheme, platform_ip, platform_port, platform_path); + assert(ok); + Error error = StartDebugserverProcess ( + platform_ip.c_str(), port, debugserver_launch_info, port); @@ -2502,10 +2543,6 @@ GDBRemoteCommunicationServer::Handle_vCont (StringExtractorGDBRemote &packet) thread_actions.Append (thread_action); } - // If a default action for all other threads wasn't mentioned - // then we should stop the threads. - thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0); - Error error = m_debugged_process_sp->Resume (thread_actions); if (error.Fail ()) { @@ -2983,7 +3020,7 @@ GDBRemoteCommunicationServer::Handle_qRegisterInfo (StringExtractorGDBRemote &pa return SendErrorResponse (69); // Return the end of registers response if we've iterated one past the end of the register set. - if (reg_index >= reg_context_sp->GetRegisterCount ()) + if (reg_index >= reg_context_sp->GetUserRegisterCount ()) return SendErrorResponse (69); const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex(reg_index); @@ -3184,10 +3221,10 @@ GDBRemoteCommunicationServer::Handle_p (StringExtractorGDBRemote &packet) } // Return the end of registers response if we've iterated one past the end of the register set. - if (reg_index >= reg_context_sp->GetRegisterCount ()) + if (reg_index >= reg_context_sp->GetUserRegisterCount ()) { if (log) - log->Printf ("GDBRemoteCommunicationServer::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetRegisterCount ()); + log->Printf ("GDBRemoteCommunicationServer::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetUserRegisterCount ()); return SendErrorResponse (0x15); } @@ -3264,7 +3301,8 @@ GDBRemoteCommunicationServer::Handle_P (StringExtractorGDBRemote &packet) } // Parse out the value. - const uint64_t raw_value = packet.GetHexMaxU64 (process_arch.GetByteOrder () == lldb::eByteOrderLittle, std::numeric_limits<uint64_t>::max ()); + uint8_t reg_bytes[32]; // big enough to support up to 256 bit ymmN register + size_t reg_size = packet.GetHexBytesAvail (reg_bytes, sizeof(reg_bytes)); // Get the thread to use. NativeThreadProtocolSP thread_sp = GetThreadFromSuffix (packet); @@ -3284,7 +3322,7 @@ GDBRemoteCommunicationServer::Handle_P (StringExtractorGDBRemote &packet) return SendErrorResponse (0x15); } - const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex(reg_index); + const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex (reg_index); if (!reg_info) { if (log) @@ -3293,20 +3331,23 @@ GDBRemoteCommunicationServer::Handle_P (StringExtractorGDBRemote &packet) } // Return the end of registers response if we've iterated one past the end of the register set. - if (reg_index >= reg_context_sp->GetRegisterCount ()) + if (reg_index >= reg_context_sp->GetUserRegisterCount ()) { if (log) - log->Printf ("GDBRemoteCommunicationServer::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetRegisterCount ()); + log->Printf ("GDBRemoteCommunicationServer::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetUserRegisterCount ()); return SendErrorResponse (0x47); } + if (reg_size != reg_info->byte_size) + { + return SendIllFormedResponse (packet, "P packet register size is incorrect"); + } // Build the reginfos response. StreamGDBRemote response; - // FIXME Could be suffixed with a thread: parameter. - // That thread then needs to be fed back into the reg context retrieval above. - Error error = reg_context_sp->WriteRegisterFromUnsigned (reg_info, raw_value); + RegisterValue reg_value (reg_bytes, reg_size, process_arch.GetByteOrder ()); + Error error = reg_context_sp->WriteRegister (reg_info, reg_value); if (error.Fail ()) { if (log) @@ -3394,6 +3435,46 @@ GDBRemoteCommunicationServer::Handle_H (StringExtractorGDBRemote &packet) } GDBRemoteCommunicationServer::PacketResult +GDBRemoteCommunicationServer::Handle_I (StringExtractorGDBRemote &packet) +{ + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); + + // Ensure we're llgs. + if (!IsGdbServer()) + return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_I() unimplemented"); + + // Fail if we don't have a current process. + if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) + { + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s failed, no process available", __FUNCTION__); + return SendErrorResponse (0x15); + } + + packet.SetFilePos (::strlen("I")); + char tmp[4096]; + for (;;) + { + size_t read = packet.GetHexBytesAvail(tmp, sizeof(tmp)); + if (read == 0) + { + break; + } + // write directly to stdin *this might block if stdin buffer is full* + // TODO: enqueue this block in circular buffer and send window size to remote host + ConnectionStatus status; + Error error; + m_stdio_communication.Write(tmp, read, status, &error); + if (error.Fail()) + { + return SendErrorResponse (0x15); + } + } + + return SendOKResponse(); +} + +GDBRemoteCommunicationServer::PacketResult GDBRemoteCommunicationServer::Handle_interrupt (StringExtractorGDBRemote &packet) { Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); @@ -3704,8 +3785,6 @@ GDBRemoteCommunicationServer::Handle_qMemoryRegionInfo (StringExtractorGDBRemote GDBRemoteCommunicationServer::PacketResult GDBRemoteCommunicationServer::Handle_Z (StringExtractorGDBRemote &packet) { - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - // We don't support if we're not llgs. if (!IsGdbServer()) return SendUnimplementedResponse (""); @@ -3713,12 +3792,13 @@ GDBRemoteCommunicationServer::Handle_Z (StringExtractorGDBRemote &packet) // Ensure we have a process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) { + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) log->Printf ("GDBRemoteCommunicationServer::%s failed, no process available", __FUNCTION__); return SendErrorResponse (0x15); } - // Parse out software or hardware breakpoint requested. + // Parse out software or hardware breakpoint or watchpoint requested. packet.SetFilePos (strlen("Z")); if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Too short Z packet, missing software/hardware specifier"); @@ -3726,61 +3806,82 @@ GDBRemoteCommunicationServer::Handle_Z (StringExtractorGDBRemote &packet) bool want_breakpoint = true; bool want_hardware = false; - const char breakpoint_type_char = packet.GetChar (); - switch (breakpoint_type_char) - { - case '0': want_hardware = false; want_breakpoint = true; break; - case '1': want_hardware = true; want_breakpoint = true; break; - case '2': want_breakpoint = false; break; - case '3': want_breakpoint = false; break; - default: + const GDBStoppointType stoppoint_type = + GDBStoppointType(packet.GetS32 (eStoppointInvalid)); + switch (stoppoint_type) + { + case eBreakpointSoftware: + want_hardware = false; want_breakpoint = true; break; + case eBreakpointHardware: + want_hardware = true; want_breakpoint = true; break; + case eWatchpointWrite: + want_hardware = true; want_breakpoint = false; break; + case eWatchpointRead: + want_hardware = true; want_breakpoint = false; break; + case eWatchpointReadWrite: + want_hardware = true; want_breakpoint = false; break; + case eStoppointInvalid: return SendIllFormedResponse(packet, "Z packet had invalid software/hardware specifier"); } if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',') - return SendIllFormedResponse(packet, "Malformed Z packet, expecting comma after breakpoint type"); + return SendIllFormedResponse(packet, "Malformed Z packet, expecting comma after stoppoint type"); - // FIXME implement watchpoint support. - if (!want_breakpoint) - return SendUnimplementedResponse ("watchpoint support not yet implemented"); - - // Parse out the breakpoint address. + // Parse out the stoppoint address. if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Too short Z packet, missing address"); - const lldb::addr_t breakpoint_addr = packet.GetHexMaxU64(false, 0); + const lldb::addr_t addr = packet.GetHexMaxU64(false, 0); if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',') return SendIllFormedResponse(packet, "Malformed Z packet, expecting comma after address"); - // Parse out the breakpoint kind (i.e. size hint for opcode size). - const uint32_t kind = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ()); - if (kind == std::numeric_limits<uint32_t>::max ()) - return SendIllFormedResponse(packet, "Malformed Z packet, failed to parse kind argument"); + // Parse out the stoppoint size (i.e. size hint for opcode size). + const uint32_t size = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ()); + if (size == std::numeric_limits<uint32_t>::max ()) + return SendIllFormedResponse(packet, "Malformed Z packet, failed to parse size argument"); if (want_breakpoint) { // Try to set the breakpoint. - const Error error = m_debugged_process_sp->SetBreakpoint (breakpoint_addr, kind, want_hardware); + const Error error = m_debugged_process_sp->SetBreakpoint (addr, size, want_hardware); if (error.Success ()) return SendOKResponse (); - else - { - if (log) - log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " failed to set breakpoint: %s", __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ()); - return SendErrorResponse (0x09); - } + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 + " failed to set breakpoint: %s", + __FUNCTION__, + m_debugged_process_sp->GetID (), + error.AsCString ()); + return SendErrorResponse (0x09); } + else + { + uint32_t watch_flags = + stoppoint_type == eWatchpointWrite + ? watch_flags = 0x1 // Write + : watch_flags = 0x3; // ReadWrite - // FIXME fix up after watchpoints are handled. - return SendUnimplementedResponse (""); + // Try to set the watchpoint. + const Error error = m_debugged_process_sp->SetWatchpoint ( + addr, size, watch_flags, want_hardware); + if (error.Success ()) + return SendOKResponse (); + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 + " failed to set watchpoint: %s", + __FUNCTION__, + m_debugged_process_sp->GetID (), + error.AsCString ()); + return SendErrorResponse (0x09); + } } GDBRemoteCommunicationServer::PacketResult GDBRemoteCommunicationServer::Handle_z (StringExtractorGDBRemote &packet) { - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - // We don't support if we're not llgs. if (!IsGdbServer()) return SendUnimplementedResponse (""); @@ -3788,66 +3889,81 @@ GDBRemoteCommunicationServer::Handle_z (StringExtractorGDBRemote &packet) // Ensure we have a process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) { + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) log->Printf ("GDBRemoteCommunicationServer::%s failed, no process available", __FUNCTION__); return SendErrorResponse (0x15); } - // Parse out software or hardware breakpoint requested. + // Parse out software or hardware breakpoint or watchpoint requested. packet.SetFilePos (strlen("z")); if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Too short z packet, missing software/hardware specifier"); bool want_breakpoint = true; - const char breakpoint_type_char = packet.GetChar (); - switch (breakpoint_type_char) + const GDBStoppointType stoppoint_type = + GDBStoppointType(packet.GetS32 (eStoppointInvalid)); + switch (stoppoint_type) { - case '0': want_breakpoint = true; break; - case '1': want_breakpoint = true; break; - case '2': want_breakpoint = false; break; - case '3': want_breakpoint = false; break; + case eBreakpointHardware: want_breakpoint = true; break; + case eBreakpointSoftware: want_breakpoint = true; break; + case eWatchpointWrite: want_breakpoint = false; break; + case eWatchpointRead: want_breakpoint = false; break; + case eWatchpointReadWrite: want_breakpoint = false; break; default: return SendIllFormedResponse(packet, "z packet had invalid software/hardware specifier"); } if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',') - return SendIllFormedResponse(packet, "Malformed z packet, expecting comma after breakpoint type"); - - // FIXME implement watchpoint support. - if (!want_breakpoint) - return SendUnimplementedResponse ("watchpoint support not yet implemented"); + return SendIllFormedResponse(packet, "Malformed z packet, expecting comma after stoppoint type"); - // Parse out the breakpoint address. + // Parse out the stoppoint address. if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Too short z packet, missing address"); - const lldb::addr_t breakpoint_addr = packet.GetHexMaxU64(false, 0); + const lldb::addr_t addr = packet.GetHexMaxU64(false, 0); if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',') return SendIllFormedResponse(packet, "Malformed z packet, expecting comma after address"); - // Parse out the breakpoint kind (i.e. size hint for opcode size). - const uint32_t kind = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ()); - if (kind == std::numeric_limits<uint32_t>::max ()) - return SendIllFormedResponse(packet, "Malformed z packet, failed to parse kind argument"); + /* + // Parse out the stoppoint size (i.e. size hint for opcode size). + const uint32_t size = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ()); + if (size == std::numeric_limits<uint32_t>::max ()) + return SendIllFormedResponse(packet, "Malformed z packet, failed to parse size argument"); + */ if (want_breakpoint) { // Try to clear the breakpoint. - const Error error = m_debugged_process_sp->RemoveBreakpoint (breakpoint_addr); + const Error error = m_debugged_process_sp->RemoveBreakpoint (addr); if (error.Success ()) return SendOKResponse (); - else - { - if (log) - log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " failed to remove breakpoint: %s", __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ()); - return SendErrorResponse (0x09); - } + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 + " failed to remove breakpoint: %s", + __FUNCTION__, + m_debugged_process_sp->GetID (), + error.AsCString ()); + return SendErrorResponse (0x09); + } + else + { + // Try to clear the watchpoint. + const Error error = m_debugged_process_sp->RemoveWatchpoint (addr); + if (error.Success ()) + return SendOKResponse (); + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 + " failed to remove watchpoint: %s", + __FUNCTION__, + m_debugged_process_sp->GetID (), + error.AsCString ()); + return SendErrorResponse (0x09); } - - // FIXME fix up after watchpoints are handled. - return SendUnimplementedResponse (""); } GDBRemoteCommunicationServer::PacketResult @@ -4283,6 +4399,30 @@ GDBRemoteCommunicationServer::Handle_qThreadStopInfo (StringExtractorGDBRemote & return SendStopReplyPacketForThread (tid); } +GDBRemoteCommunicationServer::PacketResult +GDBRemoteCommunicationServer::Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet) +{ + // Only the gdb server handles this. + if (!IsGdbServer ()) + return SendUnimplementedResponse (packet.GetStringRef ().c_str ()); + + // Fail if we don't have a current process. + if (!m_debugged_process_sp || + m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID) + return SendErrorResponse (68); + + packet.SetFilePos(strlen("qWatchpointSupportInfo")); + if (packet.GetBytesLeft() == 0) + return SendOKResponse(); + if (packet.GetChar() != ':') + return SendErrorResponse(67); + + uint32_t num = m_debugged_process_sp->GetMaxWatchpoints(); + StreamGDBRemote response; + response.Printf ("num:%d;", num); + return SendPacketNoLock(response.GetData(), response.GetSize()); +} + void GDBRemoteCommunicationServer::FlushInferiorOutput () { diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 07ce98e29ac6b..dcf07844527e1 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -23,7 +23,7 @@ #include "lldb/Target/Process.h" #include "GDBRemoteCommunication.h" -#include "../../../Host/common/NativeProcessProtocol.h" +#include "lldb/Host/common/NativeProcessProtocol.h" class ProcessGDBRemote; class StringExtractorGDBRemote; @@ -415,6 +415,9 @@ protected: Handle_H (StringExtractorGDBRemote &packet); PacketResult + Handle_I (StringExtractorGDBRemote &packet); + + PacketResult Handle_interrupt (StringExtractorGDBRemote &packet); PacketResult @@ -465,6 +468,9 @@ protected: PacketResult Handle_qThreadStopInfo (StringExtractorGDBRemote &packet); + PacketResult + Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet); + void SetCurrentThreadID (lldb::tid_t tid); diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index fe99706969c85..cb0b4bb51007b 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -42,6 +42,7 @@ #include "lldb/Core/Timer.h" #include "lldb/Core/Value.h" #include "lldb/Host/HostThread.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Host/Symbols.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/TimeValue.h" @@ -431,11 +432,11 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) } else if (name.compare("bitsize") == 0) { - reg_info.byte_size = Args::StringToUInt32(value.c_str(), 0, 0) / CHAR_BIT; + reg_info.byte_size = StringConvert::ToUInt32(value.c_str(), 0, 0) / CHAR_BIT; } else if (name.compare("offset") == 0) { - uint32_t offset = Args::StringToUInt32(value.c_str(), UINT32_MAX, 0); + uint32_t offset = StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0); if (reg_offset != offset) { reg_offset = offset; @@ -483,11 +484,11 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) } else if (name.compare("gcc") == 0) { - reg_info.kinds[eRegisterKindGCC] = Args::StringToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0); + reg_info.kinds[eRegisterKindGCC] = StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0); } else if (name.compare("dwarf") == 0) { - reg_info.kinds[eRegisterKindDWARF] = Args::StringToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0); + reg_info.kinds[eRegisterKindDWARF] = StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0); } else if (name.compare("generic") == 0) { @@ -502,7 +503,7 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) value_pair = value_pair.second.split(','); if (!value_pair.first.empty()) { - uint32_t reg = Args::StringToUInt32 (value_pair.first.str().c_str(), LLDB_INVALID_REGNUM, 16); + uint32_t reg = StringConvert::ToUInt32 (value_pair.first.str().c_str(), LLDB_INVALID_REGNUM, 16); if (reg != LLDB_INVALID_REGNUM) value_regs.push_back (reg); } @@ -517,7 +518,7 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) value_pair = value_pair.second.split(','); if (!value_pair.first.empty()) { - uint32_t reg = Args::StringToUInt32 (value_pair.first.str().c_str(), LLDB_INVALID_REGNUM, 16); + uint32_t reg = StringConvert::ToUInt32 (value_pair.first.str().c_str(), LLDB_INVALID_REGNUM, 16); if (reg != LLDB_INVALID_REGNUM) invalidate_regs.push_back (reg); } @@ -941,6 +942,7 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info) SetPrivateState (SetThreadStopInfo (m_last_stop_packet)); + m_stdio_disable = disable_stdio; if (!disable_stdio) { if (pty.GetMasterFileDescriptor() != lldb_utility::PseudoTerminal::invalid_fd) @@ -972,9 +974,12 @@ ProcessGDBRemote::ConnectToDebugserver (const char *connect_url) { Error error; // Only connect if we have a valid connect URL + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (connect_url && connect_url[0]) { + if (log) + log->Printf("ProcessGDBRemote::%s Connecting to %s", __FUNCTION__, connect_url); std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor()); if (conn_ap.get()) { @@ -1656,17 +1661,17 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) if (name.compare("metype") == 0) { // exception type in big endian hex - exc_type = Args::StringToUInt32 (value.c_str(), 0, 16); + exc_type = StringConvert::ToUInt32 (value.c_str(), 0, 16); } else if (name.compare("medata") == 0) { // exception data in big endian hex - exc_data.push_back(Args::StringToUInt64 (value.c_str(), 0, 16)); + exc_data.push_back(StringConvert::ToUInt64 (value.c_str(), 0, 16)); } else if (name.compare("thread") == 0) { // thread in big endian hex - lldb::tid_t tid = Args::StringToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); + lldb::tid_t tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); // m_thread_list_real does have its own mutex, but we need to // hold onto the mutex between the call to m_thread_list_real.FindThreadByID(...) // and the m_thread_list_real.AddThread(...) so it doesn't change on us @@ -1702,12 +1707,12 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) { value[comma_pos] = '\0'; // thread in big endian hex - tid = Args::StringToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); + tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); if (tid != LLDB_INVALID_THREAD_ID) m_thread_ids.push_back (tid); value.erase(0, comma_pos + 1); } - tid = Args::StringToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); + tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); if (tid != LLDB_INVALID_THREAD_ID) m_thread_ids.push_back (tid); } @@ -1726,7 +1731,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) } else if (name.compare("qaddr") == 0) { - thread_dispatch_qaddr = Args::StringToUInt64 (value.c_str(), 0, 16); + thread_dispatch_qaddr = StringConvert::ToUInt64 (value.c_str(), 0, 16); } else if (name.compare("reason") == 0) { @@ -1738,7 +1743,8 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) // Swap "value" over into "name_extractor" desc_extractor.GetStringRef().swap(value); // Now convert the HEX bytes into a string value - desc_extractor.GetHexByteString (thread_name); + desc_extractor.GetHexByteString (value); + description.swap(value); } else if (name.size() == 2 && ::isxdigit(name[0]) && ::isxdigit(name[1])) { @@ -1747,7 +1753,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) // so it won't have to go and read it. if (gdb_thread) { - uint32_t reg = Args::StringToUInt32 (name.c_str(), UINT32_MAX, 16); + uint32_t reg = StringConvert::ToUInt32 (name.c_str(), UINT32_MAX, 16); if (reg != UINT32_MAX) { @@ -1839,8 +1845,24 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) } else if (reason.compare("watchpoint") == 0) { - break_id_t watch_id = LLDB_INVALID_WATCH_ID; - // TODO: locate the watchpoint somehow... + StringExtractor desc_extractor(description.c_str()); + addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); + uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32); + watch_id_t watch_id = LLDB_INVALID_WATCH_ID; + if (wp_addr != LLDB_INVALID_ADDRESS) + { + WatchpointSP wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr); + if (wp_sp) + { + wp_sp->SetHardwareIndex(wp_index); + watch_id = wp_sp->GetID(); + } + } + if (watch_id == LLDB_INVALID_WATCH_ID) + { + Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_WATCHPOINTS)); + if (log) log->Printf ("failed to find watchpoint"); + } thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id)); handled = true; } @@ -2456,6 +2478,10 @@ ProcessGDBRemote::PutSTDIN (const char *src, size_t src_len, Error &error) ConnectionStatus status; m_stdio_communication.Write(src, src_len, status, NULL); } + else if (!m_stdio_disable) + { + m_gdb_comm.SendStdinNotification(src, src_len); + } return 0; } @@ -2760,6 +2786,10 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info static FileSpec g_debugserver_file_spec; ProcessLaunchInfo debugserver_launch_info; + // Make debugserver run in its own session so signals generated by + // special terminal key sequences (^C) don't affect debugserver. + debugserver_launch_info.SetLaunchInSeparateProcessGroup(true); + debugserver_launch_info.SetMonitorProcessCallback (MonitorDebugserverProcess, this, false); debugserver_launch_info.SetUserID(process_info.GetUserID()); diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp index 067449a289be0..8935f7143e488 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -13,6 +13,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/Stream.h" #include "lldb/Core/Timer.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/ObjectFile.h" @@ -992,11 +993,11 @@ DWARFCompileUnit::ParseProducerInfo () { std::string str; if (regex_match.GetMatchAtIndex (producer_cstr, 1, str)) - m_producer_version_major = Args::StringToUInt32(str.c_str(), UINT32_MAX, 10); + m_producer_version_major = StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); if (regex_match.GetMatchAtIndex (producer_cstr, 2, str)) - m_producer_version_minor = Args::StringToUInt32(str.c_str(), UINT32_MAX, 10); + m_producer_version_minor = StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); if (regex_match.GetMatchAtIndex (producer_cstr, 3, str)) - m_producer_version_update = Args::StringToUInt32(str.c_str(), UINT32_MAX, 10); + m_producer_version_update = StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); } m_producer = eProducerClang; } diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 10b51ffe0a8ad..6a8c4e6d57b90 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -2294,22 +2294,26 @@ DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr (SymbolFileDWARF* dwarf2Data, if (dwarf2Data) { offset = GetOffset(); - - const DWARFAbbreviationDeclaration* abbrev_decl = cu->GetAbbreviations()->GetAbbreviationDeclaration (m_abbr_idx); - if (abbrev_decl) + + const DWARFAbbreviationDeclarationSet *abbrev_set = cu->GetAbbreviations(); + if (abbrev_set) { - // Make sure the abbreviation code still matches. If it doesn't and - // the DWARF data was mmap'ed, the backing file might have been modified - // which is bad news. - const uint64_t abbrev_code = dwarf2Data->get_debug_info_data().GetULEB128 (&offset); - - if (abbrev_decl->Code() == abbrev_code) - return abbrev_decl; + const DWARFAbbreviationDeclaration* abbrev_decl = abbrev_set->GetAbbreviationDeclaration (m_abbr_idx); + if (abbrev_decl) + { + // Make sure the abbreviation code still matches. If it doesn't and + // the DWARF data was mmap'ed, the backing file might have been modified + // which is bad news. + const uint64_t abbrev_code = dwarf2Data->get_debug_info_data().GetULEB128 (&offset); - dwarf2Data->GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("0x%8.8x: the DWARF debug information has been modified (abbrev code was %u, and is now %u)", - GetOffset(), - (uint32_t)abbrev_decl->Code(), - (uint32_t)abbrev_code); + if (abbrev_decl->Code() == abbrev_code) + return abbrev_decl; + + dwarf2Data->GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("0x%8.8x: the DWARF debug information has been modified (abbrev code was %u, and is now %u)", + GetOffset(), + (uint32_t)abbrev_decl->Code(), + (uint32_t)abbrev_code); + } } } offset = DW_INVALID_OFFSET; diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index b3a5476227f44..7ba4f52ac2971 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -893,13 +893,22 @@ SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) // only 1 compile unit which is at offset zero in the DWARF. // TODO: modify to support LTO .o files where each .o file might // have multiple DW_TAG_compile_unit tags. - return info->GetCompileUnit(0).get(); + + DWARFCompileUnit *dwarf_cu = info->GetCompileUnit(0).get(); + if (dwarf_cu && dwarf_cu->GetUserData() == NULL) + dwarf_cu->SetUserData(comp_unit); + return dwarf_cu; } else { // Just a normal DWARF file whose user ID for the compile unit is // the DWARF offset itself - return info->GetCompileUnit((dw_offset_t)comp_unit->GetID()).get(); + + DWARFCompileUnit *dwarf_cu = info->GetCompileUnit((dw_offset_t)comp_unit->GetID()).get(); + if (dwarf_cu && dwarf_cu->GetUserData() == NULL) + dwarf_cu->SetUserData(comp_unit); + return dwarf_cu; + } } return NULL; @@ -1037,23 +1046,6 @@ SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) return cu_sp; } -static void -AddRangesToBlock (Block& block, - DWARFDebugRanges::RangeList& ranges, - addr_t block_base_addr) -{ - const size_t num_ranges = ranges.GetSize(); - for (size_t i = 0; i<num_ranges; ++i) - { - const DWARFDebugRanges::Range &range = ranges.GetEntryRef (i); - const addr_t range_base = range.GetRangeBase(); - assert (range_base >= block_base_addr); - block.AddRange(Block::Range (range_base - block_base_addr, range.GetByteSize()));; - } - block.FinalizeRanges (); -} - - Function * SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die) { @@ -1397,8 +1389,24 @@ SymbolFileDWARF::ParseFunctionBlocks subprogram_low_pc = ranges.GetMinRangeBase(0); } } - - AddRangesToBlock (*block, ranges, subprogram_low_pc); + + const size_t num_ranges = ranges.GetSize(); + for (size_t i = 0; i<num_ranges; ++i) + { + const DWARFDebugRanges::Range &range = ranges.GetEntryRef (i); + const addr_t range_base = range.GetRangeBase(); + if (range_base >= subprogram_low_pc) + block->AddRange(Block::Range (range_base - subprogram_low_pc, range.GetByteSize())); + else + { + GetObjectFile()->GetModule()->ReportError ("0x%8.8" PRIx64 ": adding range [0x%" PRIx64 "-0x%" PRIx64 ") which has a base that is less than the function's low PC 0x%" PRIx64 ". Please file a bug and attach the file at the start of this error message", + block->GetID(), + range_base, + range.GetRangeEnd(), + subprogram_low_pc); + } + } + block->FinalizeRanges (); if (tag != DW_TAG_subprogram && (name != NULL || mangled_name != NULL)) { @@ -2786,6 +2794,59 @@ SymbolFileDWARF::GetFunction (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEn return false; } + + +SymbolFileDWARF::GlobalVariableMap & +SymbolFileDWARF::GetGlobalAranges() +{ + if (!m_global_aranges_ap) + { + m_global_aranges_ap.reset (new GlobalVariableMap()); + + ModuleSP module_sp = GetObjectFile()->GetModule(); + if (module_sp) + { + const size_t num_cus = module_sp->GetNumCompileUnits(); + for (size_t i = 0; i < num_cus; ++i) + { + CompUnitSP cu_sp = module_sp->GetCompileUnitAtIndex(i); + if (cu_sp) + { + VariableListSP globals_sp = cu_sp->GetVariableList(true); + if (globals_sp) + { + const size_t num_globals = globals_sp->GetSize(); + for (size_t g = 0; g < num_globals; ++g) + { + VariableSP var_sp = globals_sp->GetVariableAtIndex(g); + if (var_sp && !var_sp->GetLocationIsConstantValueData()) + { + const DWARFExpression &location = var_sp->LocationExpression(); + Value location_result; + Error error; + if (location.Evaluate(NULL, NULL, NULL, LLDB_INVALID_ADDRESS, NULL, location_result, &error)) + { + if (location_result.GetValueType() == Value::eValueTypeFileAddress) + { + lldb::addr_t file_addr = location_result.GetScalar().ULongLong(); + lldb::addr_t byte_size = 1; + if (var_sp->GetType()) + byte_size = var_sp->GetType()->GetByteSize(); + m_global_aranges_ap->Append(GlobalVariableMap::Entry(file_addr, byte_size, var_sp.get())); + } + } + } + } + } + } + } + } + m_global_aranges_ap->Sort(); + } + return *m_global_aranges_ap; +} + + uint32_t SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) { @@ -2794,10 +2855,11 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_ static_cast<void*>(so_addr.GetSection().get()), so_addr.GetOffset(), resolve_scope); uint32_t resolved = 0; - if (resolve_scope & ( eSymbolContextCompUnit | - eSymbolContextFunction | - eSymbolContextBlock | - eSymbolContextLineEntry)) + if (resolve_scope & ( eSymbolContextCompUnit | + eSymbolContextFunction | + eSymbolContextBlock | + eSymbolContextLineEntry | + eSymbolContextVariable )) { lldb::addr_t file_vm_addr = so_addr.GetFileAddress(); @@ -2805,7 +2867,30 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_ if (debug_info) { const dw_offset_t cu_offset = debug_info->GetCompileUnitAranges().FindAddress(file_vm_addr); - if (cu_offset != DW_INVALID_OFFSET) + if (cu_offset == DW_INVALID_OFFSET) + { + // Global variables are not in the compile unit address ranges. The only way to + // currently find global variables is to iterate over the .debug_pubnames or the + // __apple_names table and find all items in there that point to DW_TAG_variable + // DIEs and then find the address that matches. + if (resolve_scope & eSymbolContextVariable) + { + GlobalVariableMap &map = GetGlobalAranges(); + const GlobalVariableMap::Entry *entry = map.FindEntryThatContains(file_vm_addr); + if (entry && entry->data) + { + Variable *variable = entry->data; + SymbolContextScope *scc = variable->GetSymbolContextScope(); + if (scc) + { + scc->CalculateSymbolContext(&sc); + sc.variable = variable; + } + return sc.GetResolvedMask(); + } + } + } + else { uint32_t cu_idx = DW_INVALID_INDEX; DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnit(cu_offset, &cu_idx).get(); @@ -3409,9 +3494,11 @@ SymbolFileDWARF::ResolveFunction (DWARFCompileUnit *cu, // Parse all blocks if needed if (inlined_die) { - sc.block = sc.function->GetBlock (true).FindBlockByID (MakeUserID(inlined_die->GetOffset())); - assert (sc.block != NULL); - if (sc.block->GetStartAddress (addr) == false) + Block &function_block = sc.function->GetBlock (true); + sc.block = function_block.FindBlockByID (MakeUserID(inlined_die->GetOffset())); + if (sc.block == NULL) + sc.block = function_block.FindBlockByID (inlined_die->GetOffset()); + if (sc.block == NULL || sc.block->GetStartAddress (addr) == false) addr.Clear(); } else @@ -6906,7 +6993,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, clang_type = pointee_clang_type.CreateMemberPointerType(class_clang_type); - byte_size = clang_type.GetByteSize(); + byte_size = clang_type.GetByteSize(nullptr); type_sp.reset( new Type (MakeUserID(die->GetOffset()), this, diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 230e1a5d3984d..d8efdbcb38a4c 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -29,6 +29,7 @@ #include "lldb/Core/ConstString.h" #include "lldb/Core/dwarf.h" #include "lldb/Core/Flags.h" +#include "lldb/Core/RangeMap.h" #include "lldb/Core/UniqueCStringMap.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/SymbolFile.h" @@ -557,6 +558,11 @@ protected: uint32_t type_mask, TypeSet &type_set); + typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, lldb_private::Variable *> GlobalVariableMap; + + GlobalVariableMap & + GetGlobalAranges(); + lldb::ModuleWP m_debug_map_module_wp; SymbolFileDWARFDebugMap * m_debug_map_symfile; clang::TranslationUnitDecl * m_clang_tu_decl; @@ -584,6 +590,7 @@ protected: std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_types_ap; std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_namespaces_ap; std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_objc_ap; + std::unique_ptr<GlobalVariableMap> m_global_aranges_ap; NameToDIE m_function_basename_index; // All concrete functions NameToDIE m_function_fullname_index; // All concrete functions NameToDIE m_function_method_index; // All inlined functions diff --git a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp index 7e484bd8dc738..0eb0f83d5f355 100644 --- a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp +++ b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp @@ -15,6 +15,7 @@ #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/Error.h" +#include "lldb/Core/FormatEntity.h" #include "lldb/Core/Log.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/StreamString.h" @@ -146,8 +147,9 @@ UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& if (log && log->GetVerbose ()) { StreamString strm; - const char *disassemble_format = "${frame.pc}: "; - inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, NULL, NULL, NULL, disassemble_format); + lldb_private::FormatEntity::Entry format; + FormatEntity::Parse("${frame.pc}: ", format); + inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, NULL, NULL, NULL, &format); log->PutCString (strm.GetData()); } |