diff options
Diffstat (limited to 'lldb')
30 files changed, 659 insertions, 120 deletions
diff --git a/lldb/cmake/modules/LLDBFramework.cmake b/lldb/cmake/modules/LLDBFramework.cmake index 81fc596..f915839 100644 --- a/lldb/cmake/modules/LLDBFramework.cmake +++ b/lldb/cmake/modules/LLDBFramework.cmake @@ -119,7 +119,7 @@ add_custom_command(TARGET liblldb POST_BUILD if(NOT APPLE_EMBEDDED) if (TARGET clang-resource-headers) add_dependencies(liblldb clang-resource-headers) - set(clang_resource_headers_dir $<TARGET_PROPERTY:clang-resource-headers,RUNTIME_OUTPUT_DIRECTORY>) + set(clang_resource_headers_dir $<TARGET_PROPERTY:clang-resource-headers,INTERFACE_INCLUDE_DIRECTORIES>) else() set(clang_resource_headers_dir ${LLDB_EXTERNAL_CLANG_RESOURCE_DIR}/include) if(NOT EXISTS ${clang_resource_headers_dir}) diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index f3b07ea..15e4585 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -1310,7 +1310,7 @@ enum CompletionType { /// Specifies if children need to be re-computed /// after a call to \ref SyntheticChildrenFrontEnd::Update. -enum class ChildCacheState { +enum ChildCacheState { eRefetch = 0, ///< Children need to be recomputed dynamically. eReuse = 1, ///< Children did not change and don't need to be recomputed; diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py index 8c29145..2ec4a84 100644 --- a/lldb/packages/Python/lldbsuite/test/dotest.py +++ b/lldb/packages/Python/lldbsuite/test/dotest.py @@ -248,7 +248,7 @@ def parseOptionsAndInitTestdirs(): configuration.compiler = which(args.compiler) if not is_exe(configuration.compiler): logging.error( - "%s is not a valid compiler executable; aborting...", args.compiler + '"%s" is not a valid compiler executable; aborting...', args.compiler ) sys.exit(-1) else: diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py index c28a78a..7a7afec 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbtest.py +++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py @@ -751,6 +751,8 @@ class Base(unittest.TestCase): "settings set symbols.enable-external-lookup false", # Inherit the TCC permissions from the inferior's parent. "settings set target.inherit-tcc true", + # Based on https://discourse.llvm.org/t/running-lldb-in-a-container/76801/4 + "settings set target.disable-aslr false", # Kill rather than detach from the inferior if something goes wrong. "settings set target.detach-on-error false", # Disable fix-its by default so that incorrect expressions in tests don't diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index cb9bee8..7ad0e5f 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -13,6 +13,7 @@ #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/Support/CodeGen.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" @@ -279,10 +280,13 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr, llvm::EngineBuilder builder(std::move(m_module_up)); llvm::Triple triple(m_module->getTargetTriple()); + // PIC needed for ELF to avoid generating 32-bit relocations (which overflow + // if the object is loaded into high memory). + bool want_pic = triple.isOSBinFormatMachO() || triple.isOSBinFormatELF(); + builder.setEngineKind(llvm::EngineKind::JIT) .setErrorStr(&error_string) - .setRelocationModel(triple.isOSBinFormatMachO() ? llvm::Reloc::PIC_ - : llvm::Reloc::Static) + .setRelocationModel(want_pic ? llvm::Reloc::PIC_ : llvm::Reloc::Static) .setMCJITMemoryManager(std::make_unique<MemoryManager>(*this)) .setOptLevel(llvm::CodeGenOptLevel::Less); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 2d306b4..31f6447 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -1049,7 +1049,6 @@ void ClangExpressionDeclMap::LookupInModulesDeclVendor( context.AddNamedDecl(copied_function); context.m_found_function_with_type_info = true; - context.m_found_function = true; } else if (auto copied_var = dyn_cast<clang::VarDecl>(copied_decl)) { context.AddNamedDecl(copied_var); context.m_found_variable = true; @@ -1299,7 +1298,6 @@ void ClangExpressionDeclMap::LookupFunction( AddOneFunction(context, sym_ctx.function, nullptr); context.m_found_function_with_type_info = true; - context.m_found_function = true; } else if (sym_ctx.symbol) { Symbol *symbol = sym_ctx.symbol; if (target && symbol->GetType() == eSymbolTypeReExported) { @@ -1331,10 +1329,8 @@ void ClangExpressionDeclMap::LookupFunction( if (!context.m_found_function_with_type_info) { if (extern_symbol) { AddOneFunction(context, nullptr, extern_symbol); - context.m_found_function = true; } else if (non_extern_symbol) { AddOneFunction(context, nullptr, non_extern_symbol); - context.m_found_function = true; } } } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.h b/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.h index dc8621dd..9a33206 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.h @@ -41,7 +41,6 @@ struct NameSearchContext { bool m_found_variable = false; bool m_found_function_with_type_info = false; - bool m_found_function = false; bool m_found_local_vars_nsp = false; bool m_found_type = false; diff --git a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt index 0c6fdb2..f59032c 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt +++ b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt @@ -14,6 +14,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN LibCxxQueue.cpp LibCxxRangesRefView.cpp LibCxxSliceArray.cpp + LibCxxProxyArray.cpp LibCxxSpan.cpp LibCxxTuple.cpp LibCxxUnorderedMap.cpp diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index afb683f..5f06841 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -762,6 +762,12 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "^std::__[[:alnum:]]+::slice_array<.+>$", stl_deref_flags, true); AddCXXSynthetic( cpp_category_sp, + lldb_private::formatters::LibcxxStdProxyArraySyntheticFrontEndCreator, + "libc++ synthetic children for the valarray proxy arrays", + "^std::__[[:alnum:]]+::(gslice|mask|indirect)_array<.+>$", + stl_deref_flags, true); + AddCXXSynthetic( + cpp_category_sp, lldb_private::formatters::LibcxxStdForwardListSyntheticFrontEndCreator, "libc++ std::forward_list synthetic children", "^std::__[[:alnum:]]+::forward_list<.+>$", stl_synth_flags, true); @@ -890,6 +896,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "libc++ std::slice_array summary provider", "^std::__[[:alnum:]]+::slice_array<.+>$", stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxContainerSummaryProvider, + "libc++ summary provider for the valarray proxy arrays", + "^std::__[[:alnum:]]+::(gslice|mask|indirect)_array<.+>$", + stl_summary_flags, true); AddCXXSummary( cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::list summary provider", diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h index 8e97174..7fe15d1 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h @@ -232,6 +232,10 @@ LibcxxStdSliceArraySyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); SyntheticChildrenFrontEnd * +LibcxxStdProxyArraySyntheticFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP); + +SyntheticChildrenFrontEnd * LibcxxStdListSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxProxyArray.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxProxyArray.cpp new file mode 100644 index 0000000..726f065 --- /dev/null +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxProxyArray.cpp @@ -0,0 +1,194 @@ +//===-- LibCxxProxyArray.cpp-----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "LibCxx.h" + +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include <optional> + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +namespace lldb_private { +namespace formatters { + +/// Data formatter for libc++'s std::"proxy_array". +/// +/// A proxy_array's are created by using: +/// std::gslice_array operator[](const std::gslice& gslicearr); +/// std::mask_array operator[](const std::valarray<bool>& boolarr); +/// std::indirect_array operator[](const std::valarray<std::size_t>& indarr); +/// +/// These arrays have the following members: +/// - __vp_ points to std::valarray::__begin_ +/// - __1d_ an array of offsets of the elements from @a __vp_ +class LibcxxStdProxyArraySyntheticFrontEnd : public SyntheticChildrenFrontEnd { +public: + LibcxxStdProxyArraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + + ~LibcxxStdProxyArraySyntheticFrontEnd() override; + + llvm::Expected<uint32_t> CalculateNumChildren() override; + + lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override; + + lldb::ChildCacheState Update() override; + + bool MightHaveChildren() override; + + size_t GetIndexOfChildWithName(ConstString name) override; + +private: + /// A non-owning pointer to the array's __vp_. + ValueObject *m_base = nullptr; + /// The type of the array's template argument T. + CompilerType m_element_type; + /// The sizeof the array's template argument T. + uint32_t m_element_size = 0; + + /// A non-owning pointer to the array's __1d_.__begin_. + ValueObject *m_start = nullptr; + /// A non-owning pointer to the array's __1d_.__end_. + ValueObject *m_finish = nullptr; + /// The type of the __1d_ array's template argument T (size_t). + CompilerType m_element_type_size_t; + /// The sizeof the __1d_ array's template argument T (size_t) + uint32_t m_element_size_size_t = 0; +}; + +} // namespace formatters +} // namespace lldb_private + +lldb_private::formatters::LibcxxStdProxyArraySyntheticFrontEnd:: + LibcxxStdProxyArraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) + : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() { + if (valobj_sp) + Update(); +} + +lldb_private::formatters::LibcxxStdProxyArraySyntheticFrontEnd:: + ~LibcxxStdProxyArraySyntheticFrontEnd() { + // these need to stay around because they are child objects who will follow + // their parent's life cycle + // delete m_base; +} + +llvm::Expected<uint32_t> lldb_private::formatters:: + LibcxxStdProxyArraySyntheticFrontEnd::CalculateNumChildren() { + + if (!m_start || !m_finish) + return 0; + uint64_t start_val = m_start->GetValueAsUnsigned(0); + uint64_t finish_val = m_finish->GetValueAsUnsigned(0); + + if (start_val == 0 || finish_val == 0) + return 0; + + if (start_val >= finish_val) + return 0; + + size_t num_children = (finish_val - start_val); + if (num_children % m_element_size_size_t) + return 0; + return num_children / m_element_size_size_t; +} + +lldb::ValueObjectSP +lldb_private::formatters::LibcxxStdProxyArraySyntheticFrontEnd::GetChildAtIndex( + uint32_t idx) { + if (!m_base) + return lldb::ValueObjectSP(); + + uint64_t offset = idx * m_element_size_size_t; + offset = offset + m_start->GetValueAsUnsigned(0); + + lldb::ValueObjectSP indirect = CreateValueObjectFromAddress( + "", offset, m_backend.GetExecutionContextRef(), m_element_type_size_t); + if (!indirect) + return lldb::ValueObjectSP(); + + const size_t value = indirect->GetValueAsUnsigned(0); + if (!value) + return lldb::ValueObjectSP(); + + offset = value * m_element_size; + offset = offset + m_base->GetValueAsUnsigned(0); + + StreamString name; + name.Printf("[%" PRIu64 "] -> [%zu]", (uint64_t)idx, value); + return CreateValueObjectFromAddress(name.GetString(), offset, + m_backend.GetExecutionContextRef(), + m_element_type); +} + +lldb::ChildCacheState +lldb_private::formatters::LibcxxStdProxyArraySyntheticFrontEnd::Update() { + m_base = nullptr; + m_start = nullptr; + m_finish = nullptr; + + CompilerType type = m_backend.GetCompilerType(); + if (type.GetNumTemplateArguments() == 0) + return ChildCacheState::eRefetch; + + m_element_type = type.GetTypeTemplateArgument(0); + if (std::optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) + m_element_size = *size; + + if (m_element_size == 0) + return ChildCacheState::eRefetch; + + ValueObjectSP vector = m_backend.GetChildMemberWithName("__1d_"); + if (!vector) + return ChildCacheState::eRefetch; + + type = vector->GetCompilerType(); + if (type.GetNumTemplateArguments() == 0) + return ChildCacheState::eRefetch; + + m_element_type_size_t = type.GetTypeTemplateArgument(0); + if (std::optional<uint64_t> size = m_element_type_size_t.GetByteSize(nullptr)) + m_element_size_size_t = *size; + + if (m_element_size_size_t == 0) + return ChildCacheState::eRefetch; + + ValueObjectSP base = m_backend.GetChildMemberWithName("__vp_"); + ValueObjectSP start = vector->GetChildMemberWithName("__begin_"); + ValueObjectSP finish = vector->GetChildMemberWithName("__end_"); + if (!base || !start || !finish) + return ChildCacheState::eRefetch; + + m_base = base.get(); + m_start = start.get(); + m_finish = finish.get(); + + return ChildCacheState::eRefetch; +} + +bool lldb_private::formatters::LibcxxStdProxyArraySyntheticFrontEnd:: + MightHaveChildren() { + return true; +} + +size_t lldb_private::formatters::LibcxxStdProxyArraySyntheticFrontEnd:: + GetIndexOfChildWithName(ConstString name) { + if (!m_base) + return std::numeric_limits<size_t>::max(); + return ExtractIndexFromString(name.GetCString()); +} + +lldb_private::SyntheticChildrenFrontEnd * +lldb_private::formatters::LibcxxStdProxyArraySyntheticFrontEndCreator( + CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { + if (!valobj_sp) + return nullptr; + return new LibcxxStdProxyArraySyntheticFrontEnd(valobj_sp); +} diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp index 5d2b4b0..59fc872 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -1089,6 +1089,10 @@ Status NativeProcessLinux::Detach() { if (GetID() == LLDB_INVALID_PROCESS_ID) return error; + // Cancel out any SIGSTOPs we may have sent while stopping the process. + // Otherwise, the process may stop as soon as we detach from it. + kill(GetID(), SIGCONT); + for (const auto &thread : m_threads) { Status e = Detach(thread->GetID()); if (e.Fail()) diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 44bd02b..be0ddb0 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -459,85 +459,19 @@ TypeSystemClang::ConvertAccessTypeToAccessSpecifier(AccessType access) { return AS_none; } -static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) { +static void ParseLangArgs(LangOptions &Opts, ArchSpec arch) { // FIXME: Cleanup per-file based stuff. - // Set some properties which depend solely on the input kind; it would be - // nice to move these to the language standard, and have the driver resolve - // the input kind + language standard. - if (IK.getLanguage() == clang::Language::Asm) { - Opts.AsmPreprocessor = 1; - } else if (IK.isObjectiveC()) { - Opts.ObjC = 1; - } - - LangStandard::Kind LangStd = LangStandard::lang_unspecified; - - if (LangStd == LangStandard::lang_unspecified) { - // Based on the base language, pick one. - switch (IK.getLanguage()) { - case clang::Language::Unknown: - case clang::Language::CIR: - case clang::Language::LLVM_IR: - case clang::Language::RenderScript: - llvm_unreachable("Invalid input kind!"); - case clang::Language::OpenCL: - LangStd = LangStandard::lang_opencl10; - break; - case clang::Language::OpenCLCXX: - LangStd = LangStandard::lang_openclcpp10; - break; - case clang::Language::Asm: - case clang::Language::C: - case clang::Language::ObjC: - LangStd = LangStandard::lang_gnu99; - break; - case clang::Language::CXX: - case clang::Language::ObjCXX: - LangStd = LangStandard::lang_gnucxx98; - break; - case clang::Language::CUDA: - case clang::Language::HIP: - LangStd = LangStandard::lang_gnucxx17; - break; - case clang::Language::HLSL: - LangStd = LangStandard::lang_hlsl; - break; - } - } - - const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); - Opts.LineComment = Std.hasLineComments(); - Opts.C99 = Std.isC99(); - Opts.CPlusPlus = Std.isCPlusPlus(); - Opts.CPlusPlus11 = Std.isCPlusPlus11(); - Opts.CPlusPlus14 = Std.isCPlusPlus14(); - Opts.CPlusPlus17 = Std.isCPlusPlus17(); - Opts.CPlusPlus20 = Std.isCPlusPlus20(); - Opts.Digraphs = Std.hasDigraphs(); - Opts.GNUMode = Std.isGNUMode(); - Opts.GNUInline = !Std.isC99(); - Opts.HexFloats = Std.hasHexFloats(); - - Opts.WChar = true; - - // OpenCL has some additional defaults. - if (LangStd == LangStandard::lang_opencl10) { - Opts.OpenCL = 1; - Opts.AltiVec = 1; - Opts.CXXOperatorNames = 1; - Opts.setLaxVectorConversions(LangOptions::LaxVectorConversionKind::All); - } - - // OpenCL and C++ both have bool, true, false keywords. - Opts.Bool = Opts.OpenCL || Opts.CPlusPlus; + std::vector<std::string> Includes; + LangOptions::setLangDefaults(Opts, clang::Language::ObjCXX, arch.GetTriple(), + Includes, clang::LangStandard::lang_gnucxx98); Opts.setValueVisibilityMode(DefaultVisibility); // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs is // specified, or -std is set to a conforming mode. Opts.Trigraphs = !Opts.GNUMode; - Opts.CharIsSigned = ArchSpec(triple).CharIsSignedByDefault(); + Opts.CharIsSigned = arch.CharIsSignedByDefault(); Opts.OptimizeSize = 0; // FIXME: Eliminate this dependency. @@ -727,8 +661,7 @@ void TypeSystemClang::CreateASTContext() { m_ast_owned = true; m_language_options_up = std::make_unique<LangOptions>(); - ParseLangArgs(*m_language_options_up, clang::Language::ObjCXX, - GetTargetTriple()); + ParseLangArgs(*m_language_options_up, ArchSpec(GetTargetTriple())); m_identifier_table_up = std::make_unique<IdentifierTable>(*m_language_options_up, nullptr); diff --git a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp index 2032c5a..6bfaa54 100644 --- a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp +++ b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp @@ -909,6 +909,9 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( if (!m_register_map_initialized) return false; + if (m_disasm_context == nullptr) + return false; + addr_t current_func_text_offset = 0; int current_sp_bytes_offset_from_fa = 0; bool is_aligned = false; @@ -1570,6 +1573,9 @@ bool x86AssemblyInspectionEngine::FindFirstNonPrologueInstruction( if (!m_register_map_initialized) return false; + if (m_disasm_context == nullptr) + return false; + while (offset < size) { int regno; int insn_len; diff --git a/lldb/test/API/commands/frame/diagnose/dereference-function-return/TestDiagnoseDereferenceFunctionReturn.py b/lldb/test/API/commands/frame/diagnose/dereference-function-return/TestDiagnoseDereferenceFunctionReturn.py index d8f4516..4d9b036 100644 --- a/lldb/test/API/commands/frame/diagnose/dereference-function-return/TestDiagnoseDereferenceFunctionReturn.py +++ b/lldb/test/API/commands/frame/diagnose/dereference-function-return/TestDiagnoseDereferenceFunctionReturn.py @@ -19,6 +19,9 @@ class TestDiagnoseDereferenceFunctionReturn(TestBase): TestBase.setUp(self) self.build() exe = self.getBuildArtifact("a.out") + # FIXME: This default changed in lldbtest.py and this test + # seems to rely on having it turned off. + self.runCmd("settings set target.disable-aslr true") self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) self.runCmd("run", RUN_SUCCEEDED) self.expect("thread list", "Thread should be stopped", substrs=["stopped"]) diff --git a/lldb/test/API/commands/process/detach-resumes/Makefile b/lldb/test/API/commands/process/detach-resumes/Makefile new file mode 100644 index 0000000..c46619c --- /dev/null +++ b/lldb/test/API/commands/process/detach-resumes/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp +ENABLE_THREADS := YES + +include Makefile.rules diff --git a/lldb/test/API/commands/process/detach-resumes/TestDetachResumes.py b/lldb/test/API/commands/process/detach-resumes/TestDetachResumes.py new file mode 100644 index 0000000..5772729 --- /dev/null +++ b/lldb/test/API/commands/process/detach-resumes/TestDetachResumes.py @@ -0,0 +1,59 @@ +""" +Test that the process continues running after we detach from it. +""" + +import lldb +import time +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class DetachResumesTestCase(TestBase): + NO_DEBUG_INFO_TESTCASE = True + + def test_detach_resumes(self): + self.build() + exe = self.getBuildArtifact() + + # The inferior will use this file to let us know it is ready to be + # attached. + sync_file_path = lldbutil.append_to_process_working_directory( + self, "sync_file_%d" % (int(time.time())) + ) + + # And this one to let us know it is running after we've detached from + # it. + exit_file_path = lldbutil.append_to_process_working_directory( + self, "exit_file_%d" % (int(time.time())) + ) + + popen = self.spawnSubprocess( + self.getBuildArtifact(exe), [sync_file_path, exit_file_path] + ) + lldbutil.wait_for_file_on_target(self, sync_file_path) + + self.runCmd("process attach -p " + str(popen.pid)) + + # Set a breakpoint at a place that will be called by multiple threads + # simultaneously. On systems (e.g. linux) where the debugger needs to + # send signals to suspend threads, these signals will race with threads + # hitting the breakpoint (and stopping on their own). + bpno = lldbutil.run_break_set_by_symbol(self, "break_here") + + # And let the inferior know it can call the function. + self.runCmd("expr -- wait_for_debugger_flag = false") + + self.runCmd("continue") + + self.expect( + "thread list", + STOPPED_DUE_TO_BREAKPOINT, + substrs=["stopped", "stop reason = breakpoint"], + ) + + # Detach, the process should keep running after this, and not be stopped + # by the signals that the debugger may have used to suspend the threads. + self.runCmd("detach") + + lldbutil.wait_for_file_on_target(self, exit_file_path) diff --git a/lldb/test/API/commands/process/detach-resumes/main.cpp b/lldb/test/API/commands/process/detach-resumes/main.cpp new file mode 100644 index 0000000..e8050fe --- /dev/null +++ b/lldb/test/API/commands/process/detach-resumes/main.cpp @@ -0,0 +1,48 @@ +#include "pseudo_barrier.h" +#include <chrono> +#include <fcntl.h> +#include <fstream> +#include <stdio.h> +#include <thread> +#include <vector> + +pseudo_barrier_t barrier; + +constexpr size_t nthreads = 5; +volatile bool wait_for_debugger_flag = true; + +void break_here() {} + +void tfunc() { + pseudo_barrier_wait(barrier); + + break_here(); +} + +int main(int argc, char const *argv[]) { + lldb_enable_attach(); + + if (argc < 3) + return 1; + + // Create a file to signal that this process has started up. + std::ofstream(argv[1]).close(); + + // And wait for it to attach. + for (int i = 0; i < 100 && wait_for_debugger_flag; ++i) + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // Fire up the threads and have them call break_here() simultaneously. + pseudo_barrier_init(barrier, nthreads); + std::vector<std::thread> threads; + for (size_t i = 0; i < nthreads; ++i) + threads.emplace_back(tfunc); + + for (std::thread &t : threads) + t.join(); + + // Create the file to let the debugger know we're running. + std::ofstream(argv[2]).close(); + + return 0; +} diff --git a/lldb/test/API/functionalities/asan/Makefile b/lldb/test/API/functionalities/asan/Makefile index 4913a18..d66696f 100644 --- a/lldb/test/API/functionalities/asan/Makefile +++ b/lldb/test/API/functionalities/asan/Makefile @@ -1,4 +1,8 @@ C_SOURCES := main.c -CFLAGS_EXTRAS := -fsanitize=address -g -gcolumn-info +asan: CFLAGS_EXTRAS := -fsanitize=address -g -gcolumn-info +asan: all + +libsanitizers: CFLAGS_EXTRAS := -fsanitize=address -fsanitize-stable-abi -g -gcolumn-info +libsanitizers: all include Makefile.rules diff --git a/lldb/test/API/functionalities/asan/TestMemoryHistory.py b/lldb/test/API/functionalities/asan/TestMemoryHistory.py index 00162ae..41ab258 100644 --- a/lldb/test/API/functionalities/asan/TestMemoryHistory.py +++ b/lldb/test/API/functionalities/asan/TestMemoryHistory.py @@ -8,16 +8,24 @@ from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbplatform from lldbsuite.test import lldbutil - +from lldbsuite.test_event.build_exception import BuildError class AsanTestCase(TestBase): @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default @expectedFailureNetBSD @skipUnlessAddressSanitizer def test(self): - self.build() + self.build(make_targets=["asan"]) self.asan_tests() + @skipIf(oslist=no_match(["macosx"])) + def test_libsanitizers_asan(self): + try: + self.build(make_targets=["libsanitizers"]) + except BuildError as e: + self.skipTest("failed to build with libsanitizers") + self.libsanitizer_tests() + def setUp(self): # Call super's setUp(). TestBase.setUp(self) @@ -26,6 +34,68 @@ class AsanTestCase(TestBase): self.line_free = line_number("main.c", "// free line") self.line_breakpoint = line_number("main.c", "// break line") + # Test line numbers: rdar://126237493 + def libsanitizer_tests(self): + target = self.createTestTarget() + + self.runCmd( + "env SanitizersAddress=1 MallocSanitizerZone=1 MallocSecureAllocator=0" + ) + + self.runCmd("run") + + # In libsanitizers, memory history is not supported until a report has been generated + self.expect( + "thread list", + "Process should be stopped due to ASan report", + substrs=["stopped", "stop reason = Use of deallocated memory"], + ) + + # test the 'memory history' command + self.expect( + "memory history 'pointer'", + substrs=[ + "Memory deallocated by Thread", + "a.out`f2", + "main.c", + "Memory allocated by Thread", + "a.out`f1", + "main.c", + ], + ) + + # do the same using SB API + process = self.dbg.GetSelectedTarget().process + val = ( + process.GetSelectedThread().GetSelectedFrame().EvaluateExpression("pointer") + ) + addr = val.GetValueAsUnsigned() + threads = process.GetHistoryThreads(addr) + self.assertEqual(threads.GetSize(), 2) + + history_thread = threads.GetThreadAtIndex(0) + self.assertTrue(history_thread.num_frames >= 2) + self.assertEqual( + history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(), + "main.c", + ) + + history_thread = threads.GetThreadAtIndex(1) + self.assertTrue(history_thread.num_frames >= 2) + self.assertEqual( + history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(), + "main.c", + ) + + # let's free the container (SBThreadCollection) and see if the + # SBThreads still live + threads = None + self.assertTrue(history_thread.num_frames >= 2) + self.assertEqual( + history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(), + "main.c", + ) + def asan_tests(self): target = self.createTestTarget() diff --git a/lldb/test/API/functionalities/asan/TestReportData.py b/lldb/test/API/functionalities/asan/TestReportData.py index 543c5fe..5e4c179 100644 --- a/lldb/test/API/functionalities/asan/TestReportData.py +++ b/lldb/test/API/functionalities/asan/TestReportData.py @@ -8,7 +8,7 @@ import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil - +from lldbsuite.test_event.build_exception import BuildError class AsanTestReportDataCase(TestBase): @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default @@ -16,9 +16,17 @@ class AsanTestReportDataCase(TestBase): @skipUnlessAddressSanitizer @skipIf(archs=["i386"], bugnumber="llvm.org/PR36710") def test(self): - self.build() + self.build(make_targets=["asan"]) self.asan_tests() + @skipIf(oslist=no_match(["macosx"])) + def test_libsanitizers_asan(self): + try: + self.build(make_targets=["libsanitizers"]) + except BuildError as e: + self.skipTest("failed to build with libsanitizers") + self.asan_tests(libsanitizers=True) + def setUp(self): # Call super's setUp(). TestBase.setUp(self) @@ -29,10 +37,15 @@ class AsanTestReportDataCase(TestBase): self.line_crash = line_number("main.c", "// BOOM line") self.col_crash = 16 - def asan_tests(self): + def asan_tests(self, libsanitizers=False): target = self.createTestTarget() - self.registerSanitizerLibrariesWithTarget(target) + if libsanitizers: + self.runCmd( + "env SanitizersAddress=1 MallocSanitizerZone=1 MallocSecureAllocator=0" + ) + else: + self.registerSanitizerLibrariesWithTarget(target) self.runCmd("run") diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/TestDataFormatterLibcxxValarray.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/TestDataFormatterLibcxxValarray.py index b59b770..613546b 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/TestDataFormatterLibcxxValarray.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/TestDataFormatterLibcxxValarray.py @@ -89,21 +89,93 @@ class LibcxxChronoDataFormatterTestCase(TestBase): "frame variable sa", substrs=[ "sa = stride=2 size=4", - "[0] = 1", - "[1] = 3", - "[2] = 5", - "[3] = 7", + "[0] = 11", + "[1] = 13", + "[2] = 15", + "[3] = 17", "}", ], ) # check access-by-index - self.expect("frame variable sa[0]", substrs=["1"]) - self.expect("frame variable sa[1]", substrs=["3"]) - self.expect("frame variable sa[2]", substrs=["5"]) - self.expect("frame variable sa[3]", substrs=["7"]) + self.expect("frame variable sa[0]", substrs=["11"]) + self.expect("frame variable sa[1]", substrs=["13"]) + self.expect("frame variable sa[2]", substrs=["15"]) + self.expect("frame variable sa[3]", substrs=["17"]) self.expect( "frame variable sa[4]", error=True, substrs=['array index 4 is not valid for "(slice_array<int>) sa"'], ) + + # + # std::gslice_array + # + + self.expect( + "frame variable ga", + substrs=[ + "ga = size=3", + "[0] -> [3] = 13", + "[1] -> [4] = 14", + "[2] -> [5] = 15", + "}", + ], + ) + + # check access-by-index + self.expect("frame variable ga[0]", substrs=["13"]) + self.expect("frame variable ga[1]", substrs=["14"]) + self.expect("frame variable ga[2]", substrs=["15"]) + self.expect( + "frame variable ga[3]", + error=True, + substrs=['array index 3 is not valid for "(gslice_array<int>) ga"'], + ) + # + # std::mask_array + # + + self.expect( + "frame variable ma", + substrs=[ + "ma = size=2", + "[0] -> [1] = 11", + "[1] -> [2] = 12", + "}", + ], + ) + + # check access-by-index + self.expect("frame variable ma[0]", substrs=["11"]) + self.expect("frame variable ma[1]", substrs=["12"]) + self.expect( + "frame variable ma[2]", + error=True, + substrs=['array index 2 is not valid for "(mask_array<int>) ma"'], + ) + + # + # std::indirect_array + # + + self.expect( + "frame variable ia", + substrs=[ + "ia = size=3", + "[0] -> [3] = 13", + "[1] -> [6] = 16", + "[2] -> [9] = 19", + "}", + ], + ) + + # check access-by-index + self.expect("frame variable ia[0]", substrs=["13"]) + self.expect("frame variable ia[1]", substrs=["16"]) + self.expect("frame variable ia[2]", substrs=["19"]) + self.expect( + "frame variable ia[3]", + error=True, + substrs=['array index 3 is not valid for "(indirect_array<int>) ia"'], + ) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/main.cpp index 1481d8b..d31951c 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/main.cpp @@ -13,8 +13,12 @@ int main() { std::valarray<double> va_double({1.0, 0.5, 0.25, 0.125}); - std::valarray<int> va({0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + std::valarray<int> va({10, 11, 12, 13, 14, 15, 16, 17, 18, 19}); std::slice_array<int> sa = va[std::slice(1, 4, 2)]; + std::gslice_array<int> ga = va[std::gslice( + 3, std::valarray<std::size_t>(3, 1), std::valarray<std::size_t>(1, 1))]; + std::mask_array<int> ma = va[std::valarray<bool>{false, true, true}]; + std::indirect_array<int> ia = va[std::valarray<size_t>{3, 6, 9}]; std::cout << "break here\n"; } diff --git a/lldb/test/API/functionalities/fork/concurrent_vfork/TestConcurrentVFork.py b/lldb/test/API/functionalities/fork/concurrent_vfork/TestConcurrentVFork.py index 1790bd4..2dcbb72 100644 --- a/lldb/test/API/functionalities/fork/concurrent_vfork/TestConcurrentVFork.py +++ b/lldb/test/API/functionalities/fork/concurrent_vfork/TestConcurrentVFork.py @@ -48,8 +48,6 @@ class TestConcurrentVFork(TestBase): self.expect("continue", patterns=[r"exited with status = 1[0-4]"]) @skipUnlessPlatform(["linux"]) - # See https://github.com/llvm/llvm-project/issues/85084. - @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_parent_vfork_no_exec(self): """ Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-parent. @@ -58,8 +56,6 @@ class TestConcurrentVFork(TestBase): self.follow_parent_helper(use_fork=False, call_exec=False) @skipUnlessPlatform(["linux"]) - # See https://github.com/llvm/llvm-project/issues/85084. - @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_parent_fork_no_exec(self): """ Make sure that debugging concurrent fork() from multiple threads won't crash lldb during follow-parent. @@ -68,8 +64,6 @@ class TestConcurrentVFork(TestBase): self.follow_parent_helper(use_fork=True, call_exec=False) @skipUnlessPlatform(["linux"]) - # See https://github.com/llvm/llvm-project/issues/85084. - @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_parent_vfork_call_exec(self): """ Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-parent. @@ -78,8 +72,6 @@ class TestConcurrentVFork(TestBase): self.follow_parent_helper(use_fork=False, call_exec=True) @skipUnlessPlatform(["linux"]) - # See https://github.com/llvm/llvm-project/issues/85084. - @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_parent_fork_call_exec(self): """ Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-parent. @@ -88,8 +80,6 @@ class TestConcurrentVFork(TestBase): self.follow_parent_helper(use_fork=True, call_exec=True) @skipUnlessPlatform(["linux"]) - # See https://github.com/llvm/llvm-project/issues/85084. - @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_child_vfork_no_exec(self): """ Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-child. @@ -98,8 +88,6 @@ class TestConcurrentVFork(TestBase): self.follow_child_helper(use_fork=False, call_exec=False) @skipUnlessPlatform(["linux"]) - # See https://github.com/llvm/llvm-project/issues/85084. - @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_child_fork_no_exec(self): """ Make sure that debugging concurrent fork() from multiple threads won't crash lldb during follow-child. @@ -108,8 +96,6 @@ class TestConcurrentVFork(TestBase): self.follow_child_helper(use_fork=True, call_exec=False) @skipUnlessPlatform(["linux"]) - # See https://github.com/llvm/llvm-project/issues/85084. - @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_child_vfork_call_exec(self): """ Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-child. @@ -118,8 +104,6 @@ class TestConcurrentVFork(TestBase): self.follow_child_helper(use_fork=False, call_exec=True) @skipUnlessPlatform(["linux"]) - # See https://github.com/llvm/llvm-project/issues/85084. - @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_child_fork_call_exec(self): """ Make sure that debugging concurrent fork() from multiple threads won't crash lldb during follow-child. diff --git a/lldb/test/Shell/lit.cfg.py b/lldb/test/Shell/lit.cfg.py index 2905695..e24f3fb 100644 --- a/lldb/test/Shell/lit.cfg.py +++ b/lldb/test/Shell/lit.cfg.py @@ -50,10 +50,14 @@ llvm_config.with_system_environment( ) # Enable sanitizer runtime flags. -config.environment["ASAN_OPTIONS"] = "detect_stack_use_after_return=1" -config.environment["TSAN_OPTIONS"] = "halt_on_error=1" -if platform.system() == "Darwin": - config.environment["MallocNanoZone"] = "0" +if "Address" in config.llvm_use_sanitizer: + config.environment["ASAN_OPTIONS"] = "detect_stack_use_after_return=1" + if platform.system() == "Darwin": + config.environment["MallocNanoZone"] = "0" + +if "Thread" in config.llvm_use_sanitizer: + config.environment["TSAN_OPTIONS"] = "halt_on_error=1" + # Support running the test suite under the lldb-repro wrapper. This makes it # possible to capture a test suite run and then rerun all the test from the diff --git a/lldb/test/Shell/lit.site.cfg.py.in b/lldb/test/Shell/lit.site.cfg.py.in index 736dfc3..b69e7bc 100644 --- a/lldb/test/Shell/lit.site.cfg.py.in +++ b/lldb/test/Shell/lit.site.cfg.py.in @@ -26,6 +26,7 @@ config.lldb_enable_lua = @LLDB_ENABLE_LUA@ config.lldb_build_directory = "@LLDB_TEST_BUILD_DIRECTORY@" config.have_lldb_server = @LLDB_TOOL_LLDB_SERVER_BUILD@ config.lldb_system_debugserver = @LLDB_USE_SYSTEM_DEBUGSERVER@ +config.llvm_use_sanitizer = "@LLVM_USE_SANITIZER@" # The shell tests use their own module caches. config.lldb_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_LLDB@", "lldb-shell") config.clang_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_CLANG@", "lldb-shell") diff --git a/lldb/unittests/UnwindAssembly/CMakeLists.txt b/lldb/unittests/UnwindAssembly/CMakeLists.txt index 136fcd9..d6e4471 100644 --- a/lldb/unittests/UnwindAssembly/CMakeLists.txt +++ b/lldb/unittests/UnwindAssembly/CMakeLists.txt @@ -9,3 +9,7 @@ endif() if ("X86" IN_LIST LLVM_TARGETS_TO_BUILD) add_subdirectory(x86) endif() + +if (NOT "X86" IN_LIST LLVM_TARGETS_TO_BUILD) + add_subdirectory(x86-but-no-x86-target) +endif() diff --git a/lldb/unittests/UnwindAssembly/x86-but-no-x86-target/CMakeLists.txt b/lldb/unittests/UnwindAssembly/x86-but-no-x86-target/CMakeLists.txt new file mode 100644 index 0000000..d28e962 --- /dev/null +++ b/lldb/unittests/UnwindAssembly/x86-but-no-x86-target/CMakeLists.txt @@ -0,0 +1,10 @@ +add_lldb_unittest(UnwindAssemblyX86ButNoX86TargetTests + Testx86AssemblyInspectionEngine.cpp + LINK_LIBS + lldbCore + lldbSymbol + lldbPluginUnwindAssemblyX86 + LINK_COMPONENTS + Support + ${LLVM_TARGETS_TO_BUILD} + ) diff --git a/lldb/unittests/UnwindAssembly/x86-but-no-x86-target/Testx86AssemblyInspectionEngine.cpp b/lldb/unittests/UnwindAssembly/x86-but-no-x86-target/Testx86AssemblyInspectionEngine.cpp new file mode 100644 index 0000000..ed093d1 --- /dev/null +++ b/lldb/unittests/UnwindAssembly/x86-but-no-x86-target/Testx86AssemblyInspectionEngine.cpp @@ -0,0 +1,103 @@ +//===-- Testx86AssemblyInspectionEngine.cpp -------------------------------===// + +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" + +#include "Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h" +#include "lldb/Core/AddressRange.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Utility/ArchSpec.h" + +#include "llvm/Support/TargetSelect.h" + +#include <memory> +#include <vector> + +using namespace lldb; +using namespace lldb_private; + +class Testx86AssemblyInspectionEngine : public testing::Test { +public: + static void SetUpTestCase(); +}; + +void Testx86AssemblyInspectionEngine::SetUpTestCase() { + llvm::InitializeAllTargets(); + llvm::InitializeAllAsmPrinters(); + llvm::InitializeAllTargetMCs(); + llvm::InitializeAllDisassemblers(); +} + +// only defining the register names / numbers that the unwinder is actually +// using today + +// names should match the constants below. These will be the eRegisterKindLLDB +// register numbers. + +const char *x86_64_reg_names[] = {"rax", "rbx", "rcx", "rdx", "rsp", "rbp", + "rsi", "rdi", "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15", "rip"}; + +enum x86_64_regs { + k_rax = 0, + k_rbx = 1, + k_rcx = 2, + k_rdx = 3, + k_rsp = 4, + k_rbp = 5, + k_rsi = 6, + k_rdi = 7, + k_r8 = 8, + k_r9 = 9, + k_r10 = 10, + k_r11 = 11, + k_r12 = 12, + k_r13 = 13, + k_r14 = 14, + k_r15 = 15, + k_rip = 16 +}; + +std::unique_ptr<x86AssemblyInspectionEngine> Getx86_64Inspector() { + + ArchSpec arch("x86_64-apple-macosx"); + std::unique_ptr<x86AssemblyInspectionEngine> engine( + new x86AssemblyInspectionEngine(arch)); + + std::vector<x86AssemblyInspectionEngine::lldb_reg_info> lldb_regnums; + int i = 0; + for (const auto &name : x86_64_reg_names) { + x86AssemblyInspectionEngine::lldb_reg_info ri; + ri.name = name; + ri.lldb_regnum = i++; + lldb_regnums.push_back(ri); + } + + engine->Initialize(lldb_regnums); + return engine; +} + +TEST_F(Testx86AssemblyInspectionEngine, TestSimple64bitFrameFunction) { + std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector(); + + // 'int main() { }' compiled for x86_64-apple-macosx with clang + uint8_t data[] = { + 0x55, // offset 0 -- pushq %rbp + 0x48, 0x89, 0xe5, // offset 1 -- movq %rsp, %rbp + 0x31, 0xc0, // offset 4 -- xorl %eax, %eax + 0x5d, // offset 6 -- popq %rbp + 0xc3 // offset 7 -- retq + }; + + AddressRange sample_range(0x1000, sizeof(data)); + + UnwindPlan unwind_plan(eRegisterKindLLDB); + EXPECT_FALSE(engine->GetNonCallSiteUnwindPlanFromAssembly( + data, sizeof(data), sample_range, unwind_plan)); +} diff --git a/lldb/unittests/tools/CMakeLists.txt b/lldb/unittests/tools/CMakeLists.txt index 055fc6e..42b0c25 100644 --- a/lldb/unittests/tools/CMakeLists.txt +++ b/lldb/unittests/tools/CMakeLists.txt @@ -1,3 +1,5 @@ if(LLDB_TOOL_LLDB_SERVER_BUILD) - add_subdirectory(lldb-server) + if (NOT LLVM_USE_SANITIZER MATCHES ".*Address.*") + add_subdirectory(lldb-server) + endif() endif() |