diff options
Diffstat (limited to 'source')
350 files changed, 10433 insertions, 4881 deletions
diff --git a/source/API/CMakeLists.txt b/source/API/CMakeLists.txt index 9dd21bcf2aaf6..c96e59be5a44a 100644 --- a/source/API/CMakeLists.txt +++ b/source/API/CMakeLists.txt @@ -2,10 +2,6 @@ if ( CMAKE_SYSTEM_NAME MATCHES "Windows" ) add_definitions( -DEXPORT_LIBLLDB ) endif() -# Include this so that add_lldb_library() has the list of dependencies -# for liblldb to link against -include(${LLDB_PROJECT_ROOT}/cmake/LLDBDependencies.cmake) - option(LLDB_BUILD_FRAMEWORK "Build the Darwin LLDB.framework" Off) if(LLDB_BUILD_FRAMEWORK AND CMAKE_VERSION VERSION_LESS 3.7) @@ -24,6 +20,8 @@ add_lldb_library(liblldb SHARED SBBlock.cpp SBBreakpoint.cpp SBBreakpointLocation.cpp + SBBreakpointName.cpp + SBBreakpointOptionCommon.cpp SBBroadcaster.cpp SBCommandInterpreter.cpp SBCommandReturnObject.cpp @@ -53,6 +51,7 @@ add_lldb_library(liblldb SHARED SBModuleSpec.cpp SBPlatform.cpp SBProcess.cpp + SBProcessInfo.cpp SBQueue.cpp SBQueueItem.cpp SBSection.cpp @@ -109,9 +108,17 @@ if (LLVM_ENABLE_WERROR) set_property(SOURCE ${LLDB_WRAP_PYTHON} APPEND_STRING PROPERTY COMPILE_FLAGS " -w") endif() endif() +set_source_files_properties(${LLDB_WRAP_PYTHON} PROPERTIES GENERATED 1) +if (CLANG_CL) + set_property(SOURCE ${LLDB_WRAP_PYTHON} APPEND_STRING + PROPERTY COMPILE_FLAGS " -Wno-unused-function") +endif() +if (LLVM_COMPILER_IS_GCC_COMPATIBLE AND + NOT "${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") + set_property(SOURCE ${LLDB_WRAP_PYTHON} APPEND_STRING + PROPERTY COMPILE_FLAGS " -Wno-sequence-point -Wno-cast-qual") +endif () -# This should not be part of LLDBDependencies.cmake, because we don't -# want every single library taking a dependency on the script interpreters. target_link_libraries(liblldb PRIVATE lldbPluginScriptInterpreterNone lldbPluginScriptInterpreterPython @@ -153,22 +160,45 @@ endif() if (LLDB_WRAP_PYTHON) add_dependencies(liblldb swig_wrapper) endif() -target_link_libraries(liblldb PRIVATE ${LLDB_SYSTEM_LIBS}) if(LLDB_BUILD_FRAMEWORK) - file(GLOB public_headers ${LLDB_SOURCE_DIR}/include/lldb/API/*.h) + file(GLOB public_headers ${LLDB_SOURCE_DIR}/include/lldb/API/*.h + ${LLDB_SOURCE_DIR}/include/lldb/lldb-*.h) + file(GLOB root_public_headers ${LLDB_SOURCE_DIR}/include/lldb/lldb-*.h) + file(GLOB root_private_headers ${LLDB_SOURCE_DIR}/include/lldb/lldb-private*.h) + list(REMOVE_ITEM root_public_headers ${root_private_headers}) + + foreach(header ${public_headers} ${root_public_headers} ${LLDB_SOURCE_DIR}/include/lldb/Utility/SharingPtr.h) + get_filename_component(basename ${header} NAME) + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/FrameworkHeaders/${basename} + DEPENDS ${header} + COMMAND ${CMAKE_COMMAND} -E copy ${header} ${CMAKE_CURRENT_BINARY_DIR}/FrameworkHeaders/${basename}) + list(APPEND framework_headers ${CMAKE_CURRENT_BINARY_DIR}/FrameworkHeaders/${basename}) + endforeach() + + add_custom_target(lldb-framework-headers DEPENDS ${framework_headers} + COMMAND ${LLDB_SOURCE_DIR}/scripts/framework-header-fix.sh ${CMAKE_CURRENT_BINARY_DIR}/FrameworkHeaders ${LLDB_VERSION}) + add_dependencies(liblldb lldb-framework-headers) + set_target_properties(liblldb PROPERTIES OUTPUT_NAME LLDB FRAMEWORK On FRAMEWORK_VERSION ${LLDB_FRAMEWORK_VERSION} LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${LLDB_FRAMEWORK_INSTALL_DIR} - PUBLIC_HEADER "${public_headers}") + PUBLIC_HEADER "${framework_headers}") + + if(NOT IOS) + add_custom_command(TARGET liblldb POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/FrameworkHeaders $<TARGET_FILE_DIR:liblldb>/Headers + COMMAND ${CMAKE_COMMAND} -E create_symlink Versions/Current/Headers ${CMAKE_BINARY_DIR}/${LLDB_FRAMEWORK_INSTALL_DIR}/LLDB.framework/Headers + COMMAND ${CMAKE_COMMAND} -E create_symlink ${LLDB_FRAMEWORK_VERSION} ${CMAKE_BINARY_DIR}/${LLDB_FRAMEWORK_INSTALL_DIR}/LLDB.framework/Versions/Current + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/clang/${LLDB_VERSION} $<TARGET_FILE_DIR:liblldb>/Resources/Clang + ) + else() + add_custom_command(TARGET liblldb POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/FrameworkHeaders $<TARGET_FILE_DIR:liblldb>/Headers + ) + endif() - add_custom_command(TARGET liblldb POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_FILE_DIR:liblldb>/Versions/${LLDB_FRAMEWORK_VERSION} - COMMAND ${CMAKE_COMMAND} -E copy_directory ${LLDB_SOURCE_DIR}/include/lldb/API $<TARGET_FILE_DIR:liblldb>/Headers - COMMAND ${CMAKE_COMMAND} -E create_symlink Versions/Current/Headers ${CMAKE_BINARY_DIR}/${LLDB_FRAMEWORK_INSTALL_DIR}/LLDB.framework/Headers - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/clang/${LLDB_VERSION} $<TARGET_FILE_DIR:liblldb>/Resources/Clang - ) endif() diff --git a/source/API/SBBreakpoint.cpp b/source/API/SBBreakpoint.cpp index bf9603248d71f..6a0ff9536c2c2 100644 --- a/source/API/SBBreakpoint.cpp +++ b/source/API/SBBreakpoint.cpp @@ -37,6 +37,8 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/Stream.h" +#include "SBBreakpointOptionCommon.h" + #include "lldb/lldb-enumerations.h" #include "llvm/ADT/STLExtras.h" @@ -44,21 +46,6 @@ using namespace lldb; using namespace lldb_private; -struct CallbackData { - SBBreakpoint::BreakpointHitCallback callback; - void *callback_baton; -}; - -class SBBreakpointCallbackBaton : public TypedBaton<CallbackData> { -public: - SBBreakpointCallbackBaton(SBBreakpoint::BreakpointHitCallback callback, - void *baton) - : TypedBaton(llvm::make_unique<CallbackData>()) { - getItem()->callback = callback; - getItem()->callback_baton = baton; - } -}; - SBBreakpoint::SBBreakpoint() {} SBBreakpoint::SBBreakpoint(const SBBreakpoint &rhs) @@ -264,6 +251,25 @@ const char *SBBreakpoint::GetCondition() { return nullptr; } +void SBBreakpoint::SetAutoContinue(bool auto_continue) { + BreakpointSP bkpt_sp = GetSP(); + if (bkpt_sp) { + std::lock_guard<std::recursive_mutex> guard( + bkpt_sp->GetTarget().GetAPIMutex()); + bkpt_sp->SetAutoContinue(auto_continue); + } +} + +bool SBBreakpoint::GetAutoContinue() { + BreakpointSP bkpt_sp = GetSP(); + if (bkpt_sp) { + std::lock_guard<std::recursive_mutex> guard( + bkpt_sp->GetTarget().GetAPIMutex()); + return bkpt_sp->IsAutoContinue(); + } + return false; +} + uint32_t SBBreakpoint::GetHitCount() const { uint32_t count = 0; BreakpointSP bkpt_sp = GetSP(); @@ -481,37 +487,9 @@ bool SBBreakpoint::GetDescription(SBStream &s, bool include_locations) { return false; } -bool SBBreakpoint::PrivateBreakpointHitCallback(void *baton, - StoppointCallbackContext *ctx, - lldb::user_id_t break_id, - lldb::user_id_t break_loc_id) { - ExecutionContext exe_ctx(ctx->exe_ctx_ref); - BreakpointSP bp_sp( - exe_ctx.GetTargetRef().GetBreakpointList().FindBreakpointByID(break_id)); - if (baton && bp_sp) { - CallbackData *data = (CallbackData *)baton; - lldb_private::Breakpoint *bp = bp_sp.get(); - if (bp && data->callback) { - Process *process = exe_ctx.GetProcessPtr(); - if (process) { - SBProcess sb_process(process->shared_from_this()); - SBThread sb_thread; - SBBreakpointLocation sb_location; - assert(bp_sp); - sb_location.SetLocation(bp_sp->FindLocationByID(break_loc_id)); - Thread *thread = exe_ctx.GetThreadPtr(); - if (thread) - sb_thread.SetThread(thread->shared_from_this()); - - return data->callback(data->callback_baton, sb_process, sb_thread, - sb_location); - } - } - } - return true; // Return true if we should stop at this breakpoint -} - -void SBBreakpoint::SetCallback(BreakpointHitCallback callback, void *baton) { +void SBBreakpoint + ::SetCallback(SBBreakpointHitCallback callback, + void *baton) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); BreakpointSP bkpt_sp = GetSP(); LLDB_LOG(log, "breakpoint = {0}, callback = {1}, baton = {2}", bkpt_sp.get(), @@ -521,7 +499,8 @@ void SBBreakpoint::SetCallback(BreakpointHitCallback callback, void *baton) { std::lock_guard<std::recursive_mutex> guard( bkpt_sp->GetTarget().GetAPIMutex()); BatonSP baton_sp(new SBBreakpointCallbackBaton(callback, baton)); - bkpt_sp->SetCallback(SBBreakpoint::PrivateBreakpointHitCallback, baton_sp, + bkpt_sp->SetCallback(SBBreakpointCallbackBaton + ::PrivateBreakpointHitCallback, baton_sp, false); } } @@ -580,10 +559,17 @@ bool SBBreakpoint::AddName(const char *new_name) { bkpt_sp->GetTarget().GetAPIMutex()); Status error; // Think I'm just going to swallow the error here, it's // probably more annoying to have to provide it. - return bkpt_sp->AddName(new_name, error); + bkpt_sp->GetTarget().AddNameToBreakpoint(bkpt_sp, new_name, error); + if (error.Fail()) + { + if (log) + log->Printf("Failed to add name: '%s' to breakpoint: %s", + new_name, error.AsCString()); + return false; + } } - return false; + return true; } void SBBreakpoint::RemoveName(const char *name_to_remove) { @@ -594,7 +580,8 @@ void SBBreakpoint::RemoveName(const char *name_to_remove) { if (bkpt_sp) { std::lock_guard<std::recursive_mutex> guard( bkpt_sp->GetTarget().GetAPIMutex()); - bkpt_sp->RemoveName(name_to_remove); + bkpt_sp->GetTarget().RemoveNameFromBreakpoint(bkpt_sp, + ConstString(name_to_remove)); } } diff --git a/source/API/SBBreakpointLocation.cpp b/source/API/SBBreakpointLocation.cpp index dc9c00d8dd57e..99ac0277e7000 100644 --- a/source/API/SBBreakpointLocation.cpp +++ b/source/API/SBBreakpointLocation.cpp @@ -12,6 +12,7 @@ #include "lldb/API/SBDebugger.h" #include "lldb/API/SBDefines.h" #include "lldb/API/SBStream.h" +#include "lldb/API/SBStringList.h" #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointLocation.h" @@ -100,6 +101,16 @@ bool SBBreakpointLocation::IsEnabled() { return false; } +uint32_t SBBreakpointLocation::GetHitCount() { + BreakpointLocationSP loc_sp = GetSP(); + if (loc_sp) { + std::lock_guard<std::recursive_mutex> guard( + loc_sp->GetTarget().GetAPIMutex()); + return loc_sp->GetHitCount(); + } else + return 0; +} + uint32_t SBBreakpointLocation::GetIgnoreCount() { BreakpointLocationSP loc_sp = GetSP(); if (loc_sp) { @@ -138,6 +149,25 @@ const char *SBBreakpointLocation::GetCondition() { return NULL; } +void SBBreakpointLocation::SetAutoContinue(bool auto_continue) { + BreakpointLocationSP loc_sp = GetSP(); + if (loc_sp) { + std::lock_guard<std::recursive_mutex> guard( + loc_sp->GetTarget().GetAPIMutex()); + loc_sp->SetAutoContinue(auto_continue); + } +} + +bool SBBreakpointLocation::GetAutoContinue() { + BreakpointLocationSP loc_sp = GetSP(); + if (loc_sp) { + std::lock_guard<std::recursive_mutex> guard( + loc_sp->GetTarget().GetAPIMutex()); + return loc_sp->IsAutoContinue(); + } + return false; +} + void SBBreakpointLocation::SetScriptCallbackFunction( const char *callback_function_name) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); @@ -185,6 +215,33 @@ SBBreakpointLocation::SetScriptCallbackBody(const char *callback_body_text) { return sb_error; } +void SBBreakpointLocation::SetCommandLineCommands(SBStringList &commands) { + BreakpointLocationSP loc_sp = GetSP(); + if (!loc_sp) + return; + if (commands.GetSize() == 0) + return; + + std::lock_guard<std::recursive_mutex> guard( + loc_sp->GetTarget().GetAPIMutex()); + std::unique_ptr<BreakpointOptions::CommandData> cmd_data_up( + new BreakpointOptions::CommandData(*commands, eScriptLanguageNone)); + + loc_sp->GetLocationOptions()->SetCommandDataCallback(cmd_data_up); +} + +bool SBBreakpointLocation::GetCommandLineCommands(SBStringList &commands) { + BreakpointLocationSP loc_sp = GetSP(); + if (!loc_sp) + return false; + StringList command_list; + bool has_commands = + loc_sp->GetLocationOptions()->GetCommandLineCallbacks(command_list); + if (has_commands) + commands.AppendList(command_list); + return has_commands; +} + void SBBreakpointLocation::SetThreadID(tid_t thread_id) { BreakpointLocationSP loc_sp = GetSP(); if (loc_sp) { diff --git a/source/API/SBBreakpointName.cpp b/source/API/SBBreakpointName.cpp new file mode 100644 index 0000000000000..2205280b9e5f2 --- /dev/null +++ b/source/API/SBBreakpointName.cpp @@ -0,0 +1,685 @@ +//===-- SBBreakpointName.cpp ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/API/SBBreakpointName.h" +#include "lldb/API/SBDebugger.h" +#include "lldb/API/SBError.h" +#include "lldb/API/SBStream.h" +#include "lldb/API/SBStringList.h" +#include "lldb/API/SBTarget.h" + +#include "lldb/Breakpoint/BreakpointName.h" +#include "lldb/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/ScriptInterpreter.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/ThreadSpec.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Stream.h" + +#include "SBBreakpointOptionCommon.h" + +using namespace lldb; +using namespace lldb_private; + +namespace lldb +{ +class SBBreakpointNameImpl { +public: + SBBreakpointNameImpl(TargetSP target_sp, const char *name) { + if (!name || name[0] == '\0') + return; + m_name.assign(name); + + if (!target_sp) + return; + + m_target_wp = target_sp; + } + + SBBreakpointNameImpl(SBTarget &sb_target, const char *name); + bool operator==(const SBBreakpointNameImpl &rhs); + bool operator!=(const SBBreakpointNameImpl &rhs); + + // For now we take a simple approach and only keep the name, and relook + // up the location when we need it. + + TargetSP GetTarget() const { + return m_target_wp.lock(); + } + + const char *GetName() const { + return m_name.c_str(); + } + + bool IsValid() const { + return !m_name.empty() && m_target_wp.lock(); + } + + lldb_private::BreakpointName *GetBreakpointName() const; + +private: + TargetWP m_target_wp; + std::string m_name; +}; + +SBBreakpointNameImpl::SBBreakpointNameImpl(SBTarget &sb_target, + const char *name) { + if (!name || name[0] == '\0') + return; + m_name.assign(name); + + if (!sb_target.IsValid()) + return; + + TargetSP target_sp = sb_target.GetSP(); + if (!target_sp) + return; + + m_target_wp = target_sp; +} + +bool SBBreakpointNameImpl::operator==(const SBBreakpointNameImpl &rhs) { + return m_name == rhs.m_name && m_target_wp.lock() == rhs.m_target_wp.lock(); +} + +bool SBBreakpointNameImpl::operator!=(const SBBreakpointNameImpl &rhs) { + return m_name != rhs.m_name || m_target_wp.lock() != rhs.m_target_wp.lock(); +} + +lldb_private::BreakpointName *SBBreakpointNameImpl::GetBreakpointName() const { + if (!IsValid()) + return nullptr; + TargetSP target_sp = GetTarget(); + if (!target_sp) + return nullptr; + Status error; + return target_sp->FindBreakpointName(ConstString(m_name), true, error); +} + +} // namespace lldb + +SBBreakpointName::SBBreakpointName() {} + +SBBreakpointName::SBBreakpointName(SBTarget &sb_target, const char *name) +{ + m_impl_up.reset(new SBBreakpointNameImpl(sb_target, name)); + // Call FindBreakpointName here to make sure the name is valid, reset if + // not: + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + m_impl_up.reset(); +} + +SBBreakpointName::SBBreakpointName(SBBreakpoint &sb_bkpt, const char *name) +{ + if (!sb_bkpt.IsValid()) { + m_impl_up.reset(); + return; + } + BreakpointSP bkpt_sp = sb_bkpt.GetSP(); + Target &target = bkpt_sp->GetTarget(); + + m_impl_up.reset(new SBBreakpointNameImpl(target.shared_from_this(), name)); + + // Call FindBreakpointName here to make sure the name is valid, reset if + // not: + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) { + m_impl_up.reset(); + return; + } + + // Now copy over the breakpoint's options: + target.ConfigureBreakpointName(*bp_name, *bkpt_sp->GetOptions(), + BreakpointName::Permissions()); +} + +SBBreakpointName::SBBreakpointName(const SBBreakpointName &rhs) +{ + if (!rhs.m_impl_up) + return; + else + m_impl_up.reset(new SBBreakpointNameImpl(rhs.m_impl_up->GetTarget(), + rhs.m_impl_up->GetName())); +} + +SBBreakpointName::~SBBreakpointName() = default; + +const SBBreakpointName &SBBreakpointName::operator=(const SBBreakpointName &rhs) +{ + if (!rhs.m_impl_up) { + m_impl_up.reset(); + return *this; + } + + m_impl_up.reset(new SBBreakpointNameImpl(rhs.m_impl_up->GetTarget(), + rhs.m_impl_up->GetName())); + return *this; +} + +bool SBBreakpointName::operator==(const lldb::SBBreakpointName &rhs) { + return *m_impl_up.get() == *rhs.m_impl_up.get(); +} + +bool SBBreakpointName::operator!=(const lldb::SBBreakpointName &rhs) { + return *m_impl_up.get() != *rhs.m_impl_up.get(); +} + +bool SBBreakpointName::IsValid() const { + if (!m_impl_up) + return false; + return m_impl_up->IsValid(); +} + +const char *SBBreakpointName::GetName() const { + if (!m_impl_up) + return "<Invalid Breakpoint Name Object>"; + return m_impl_up->GetName(); +} + +void SBBreakpointName::SetEnabled(bool enable) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return; + + LLDB_LOG(log, "Name: {0} enabled: {1}\n", bp_name->GetName(), enable); + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + bp_name->GetOptions().SetEnabled(enable); +} + +void SBBreakpointName::UpdateName(BreakpointName &bp_name) { + if (!IsValid()) + return; + + TargetSP target_sp = m_impl_up->GetTarget(); + if (!target_sp) + return; + target_sp->ApplyNameToBreakpoints(bp_name); + +} + +bool SBBreakpointName::IsEnabled() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return false; + + LLDB_LOG(log, "Name: {0}\n", bp_name->GetName()); + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + return bp_name->GetOptions().IsEnabled(); +} + +void SBBreakpointName::SetOneShot(bool one_shot) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return; + + LLDB_LOG(log, "Name: {0} one_shot: {1}\n", bp_name->GetName(), one_shot); + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + bp_name->GetOptions().SetOneShot(one_shot); + UpdateName(*bp_name); +} + +bool SBBreakpointName::IsOneShot() const { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + const BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return false; + + LLDB_LOG(log, "Name: {0}\n", bp_name->GetName()); + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + return bp_name->GetOptions().IsOneShot(); +} + +void SBBreakpointName::SetIgnoreCount(uint32_t count) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return; + + LLDB_LOG(log, "Name: {0} one_shot: {1}\n", bp_name->GetName(), count); + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + bp_name->GetOptions().SetIgnoreCount(count); + UpdateName(*bp_name); +} + +uint32_t SBBreakpointName::GetIgnoreCount() const { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return false; + + LLDB_LOG(log, "Name: {0}\n", bp_name->GetName()); + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + return bp_name->GetOptions().GetIgnoreCount(); +} + +void SBBreakpointName::SetCondition(const char *condition) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return; + + LLDB_LOG(log, "Name: {0} one_shot: {1}\n", bp_name->GetName(), + condition ? condition : "<NULL>"); + + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + bp_name->GetOptions().SetCondition(condition); + UpdateName(*bp_name); +} + +const char *SBBreakpointName::GetCondition() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return nullptr; + + LLDB_LOG(log, "Name: {0}\n", bp_name->GetName()); + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + return bp_name->GetOptions().GetConditionText(); +} + +void SBBreakpointName::SetAutoContinue(bool auto_continue) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return; + + LLDB_LOG(log, "Name: {0} auto-continue: {1}\n", bp_name->GetName(), auto_continue); + + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + bp_name->GetOptions().SetAutoContinue(auto_continue); + UpdateName(*bp_name); +} + +bool SBBreakpointName::GetAutoContinue() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return false; + + LLDB_LOG(log, "Name: {0}\n", bp_name->GetName()); + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + return bp_name->GetOptions().IsAutoContinue(); +} + +void SBBreakpointName::SetThreadID(tid_t tid) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return; + + LLDB_LOG(log, "Name: {0} tid: {1:x}\n", bp_name->GetName(), tid); + + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + bp_name->GetOptions().SetThreadID(tid); + UpdateName(*bp_name); +} + +tid_t SBBreakpointName::GetThreadID() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return LLDB_INVALID_THREAD_ID; + + LLDB_LOG(log, "Name: {0}\n", bp_name->GetName()); + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + return bp_name->GetOptions().GetThreadSpec()->GetTID(); +} + +void SBBreakpointName::SetThreadIndex(uint32_t index) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return; + + LLDB_LOG(log, "Name: {0} thread index: {1}\n", bp_name->GetName(), index); + + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + bp_name->GetOptions().GetThreadSpec()->SetIndex(index); + UpdateName(*bp_name); +} + +uint32_t SBBreakpointName::GetThreadIndex() const { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return LLDB_INVALID_THREAD_ID; + + LLDB_LOG(log, "Name: {0}\n", bp_name->GetName()); + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + return bp_name->GetOptions().GetThreadSpec()->GetIndex(); +} + +void SBBreakpointName::SetThreadName(const char *thread_name) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return; + + LLDB_LOG(log, "Name: {0} thread name: {1}\n", bp_name->GetName(), thread_name); + + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + bp_name->GetOptions().GetThreadSpec()->SetName(thread_name); + UpdateName(*bp_name); +} + +const char *SBBreakpointName::GetThreadName() const { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return nullptr; + + LLDB_LOG(log, "Name: {0}\n", bp_name->GetName()); + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + return bp_name->GetOptions().GetThreadSpec()->GetName(); +} + +void SBBreakpointName::SetQueueName(const char *queue_name) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return; + + LLDB_LOG(log, "Name: {0} queue name: {1}\n", bp_name->GetName(), queue_name); + + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + bp_name->GetOptions().GetThreadSpec()->SetQueueName(queue_name); + UpdateName(*bp_name); +} + +const char *SBBreakpointName::GetQueueName() const { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return nullptr; + + LLDB_LOG(log, "Name: {0}\n", bp_name->GetName()); + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + return bp_name->GetOptions().GetThreadSpec()->GetQueueName(); +} + +void SBBreakpointName::SetCommandLineCommands(SBStringList &commands) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return; + if (commands.GetSize() == 0) + return; + + LLDB_LOG(log, "Name: {0} commands\n", bp_name->GetName()); + + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + std::unique_ptr<BreakpointOptions::CommandData> cmd_data_up( + new BreakpointOptions::CommandData(*commands, eScriptLanguageNone)); + + bp_name->GetOptions().SetCommandDataCallback(cmd_data_up); + UpdateName(*bp_name); +} + +bool SBBreakpointName::GetCommandLineCommands(SBStringList &commands) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return false; + + LLDB_LOG(log, "Name: {0}\n", bp_name->GetName()); + StringList command_list; + bool has_commands = + bp_name->GetOptions().GetCommandLineCallbacks(command_list); + if (has_commands) + commands.AppendList(command_list); + return has_commands; +} + +const char *SBBreakpointName::GetHelpString() const { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return ""; + + LLDB_LOG(log, "Help: {0}\n", bp_name->GetHelp()); + return bp_name->GetHelp(); +} + +void SBBreakpointName::SetHelpString(const char *help_string) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return; + + LLDB_LOG(log, "Name: {0} help: {1}\n", bp_name->GetName(), help_string); + + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + bp_name->SetHelp(help_string); +} + +bool SBBreakpointName::GetDescription(SBStream &s) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + { + s.Printf("No value"); + return false; + } + + LLDB_LOG(log, "Name: {0}\n", bp_name->GetName()); + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + bp_name->GetDescription(s.get(), eDescriptionLevelFull); + return true; +} + +void SBBreakpointName::SetCallback(SBBreakpointHitCallback callback, + void *baton) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return; + LLDB_LOG(log, "callback = {1}, baton = {2}", callback, baton); + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + BatonSP baton_sp(new SBBreakpointCallbackBaton(callback, baton)); + bp_name->GetOptions().SetCallback(SBBreakpointCallbackBaton + ::PrivateBreakpointHitCallback, + baton_sp, + false); + UpdateName(*bp_name); +} + +void SBBreakpointName::SetScriptCallbackFunction( + const char *callback_function_name) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return; + + LLDB_LOG(log, "Name: {0} callback: {1}\n", bp_name->GetName(), + callback_function_name); + + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + BreakpointOptions &bp_options = bp_name->GetOptions(); + m_impl_up->GetTarget() + ->GetDebugger() + .GetCommandInterpreter() + .GetScriptInterpreter() + ->SetBreakpointCommandCallbackFunction(&bp_options, + callback_function_name); + UpdateName(*bp_name); +} + +SBError SBBreakpointName::SetScriptCallbackBody(const char *callback_body_text) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + SBError sb_error; + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return sb_error; + + LLDB_LOG(log, "Name: {0} callback: {1}\n", bp_name->GetName(), + callback_body_text); + + std::lock_guard<std::recursive_mutex> guard( + m_impl_up->GetTarget()->GetAPIMutex()); + + BreakpointOptions &bp_options = bp_name->GetOptions(); + Status error = + m_impl_up->GetTarget() + ->GetDebugger() + .GetCommandInterpreter() + .GetScriptInterpreter() + ->SetBreakpointCommandCallback(&bp_options, callback_body_text); + sb_error.SetError(error); + if (!sb_error.Fail()) + UpdateName(*bp_name); + + return sb_error; +} + +bool SBBreakpointName::GetAllowList() const +{ + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return false; + return bp_name->GetPermissions().GetAllowList(); +} + +void SBBreakpointName::SetAllowList(bool value) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return; + if (log) + log->Printf("Setting allow list to %u for %s.", value, + bp_name->GetName().AsCString()); + bp_name->GetPermissions().SetAllowList(value); +} + +bool SBBreakpointName::GetAllowDelete() +{ + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return false; + return bp_name->GetPermissions().GetAllowDelete(); +} + +void SBBreakpointName::SetAllowDelete(bool value) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return; + if (log) + log->Printf("Setting allow delete to %u for %s.", value, + bp_name->GetName().AsCString()); + bp_name->GetPermissions().SetAllowDelete(value); +} + +bool SBBreakpointName::GetAllowDisable() +{ + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return false; + return bp_name->GetPermissions().GetAllowDisable(); +} + +void SBBreakpointName::SetAllowDisable(bool value) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + BreakpointName *bp_name = GetBreakpointName(); + if (!bp_name) + return; + if (log) + log->Printf("Setting allow disable to %u for %s.", value, + bp_name->GetName().AsCString()); + bp_name->GetPermissions().SetAllowDisable(value); +} + +lldb_private::BreakpointName *SBBreakpointName::GetBreakpointName() const +{ + if (!IsValid()) + return nullptr; + return m_impl_up->GetBreakpointName(); +} + diff --git a/source/API/SBBreakpointOptionCommon.cpp b/source/API/SBBreakpointOptionCommon.cpp new file mode 100644 index 0000000000000..569b860a4235a --- /dev/null +++ b/source/API/SBBreakpointOptionCommon.cpp @@ -0,0 +1,85 @@ +//===-- SBBreakpointName.cpp ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/API/SBBreakpointName.h" +#include "lldb/API/SBBreakpointLocation.h" +#include "lldb/API/SBDebugger.h" +#include "lldb/API/SBEvent.h" +#include "lldb/API/SBProcess.h" +#include "lldb/API/SBStream.h" +#include "lldb/API/SBStringList.h" +#include "lldb/API/SBThread.h" + +#include "lldb/Breakpoint/BreakpointName.h" +#include "lldb/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/ScriptInterpreter.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadSpec.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Stream.h" + +#include "lldb/lldb-enumerations.h" + +#include "SBBreakpointOptionCommon.h" + +#include "llvm/ADT/STLExtras.h" + +using namespace lldb; +using namespace lldb_private; + +SBBreakpointCallbackBaton::SBBreakpointCallbackBaton(SBBreakpointHitCallback + callback, + void *baton) + : TypedBaton(llvm::make_unique<CallbackData>()) { + getItem()->callback = callback; + getItem()->callback_baton = baton; + } + + bool SBBreakpointCallbackBaton::PrivateBreakpointHitCallback(void *baton, + StoppointCallbackContext *ctx, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id) +{ + ExecutionContext exe_ctx(ctx->exe_ctx_ref); + BreakpointSP bp_sp( + exe_ctx.GetTargetRef().GetBreakpointList().FindBreakpointByID(break_id)); + if (baton && bp_sp) { + CallbackData *data = (CallbackData *)baton; + lldb_private::Breakpoint *bp = bp_sp.get(); + if (bp && data->callback) { + Process *process = exe_ctx.GetProcessPtr(); + if (process) { + SBProcess sb_process(process->shared_from_this()); + SBThread sb_thread; + SBBreakpointLocation sb_location; + assert(bp_sp); + sb_location.SetLocation(bp_sp->FindLocationByID(break_loc_id)); + Thread *thread = exe_ctx.GetThreadPtr(); + if (thread) + sb_thread.SetThread(thread->shared_from_this()); + + return data->callback(data->callback_baton, sb_process, sb_thread, + sb_location); + } + } + } + return true; // Return true if we should stop at this breakpoint +} + +SBBreakpointCallbackBaton::~SBBreakpointCallbackBaton() = default; diff --git a/source/API/SBBreakpointOptionCommon.h b/source/API/SBBreakpointOptionCommon.h new file mode 100644 index 0000000000000..fe276ac636fef --- /dev/null +++ b/source/API/SBBreakpointOptionCommon.h @@ -0,0 +1,37 @@ +//===-- SBBreakpointOptionCommon.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SBBreakpointOptionCommons_h_ +#define LLDB_SBBreakpointOptionCommons_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/Utility/Baton.h" + +namespace lldb +{ +struct CallbackData { + SBBreakpointHitCallback callback; + void *callback_baton; +}; + +class SBBreakpointCallbackBaton : public lldb_private::TypedBaton<CallbackData> { +public: + SBBreakpointCallbackBaton(SBBreakpointHitCallback callback, + void *baton); + + ~SBBreakpointCallbackBaton(); + + static bool PrivateBreakpointHitCallback(void *baton, + lldb_private::StoppointCallbackContext *ctx, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id); +}; + +} // namespace lldb +#endif // LLDB_SBBreakpointOptionCommons_h_ diff --git a/source/API/SBCommandInterpreter.cpp b/source/API/SBCommandInterpreter.cpp index aa4953999b84e..c9bb8f65fa2e9 100644 --- a/source/API/SBCommandInterpreter.cpp +++ b/source/API/SBCommandInterpreter.cpp @@ -161,6 +161,10 @@ bool SBCommandInterpreter::IsActive() { return (IsValid() ? m_opaque_ptr->IsActive() : false); } +bool SBCommandInterpreter::WasInterrupted() const { + return (IsValid() ? m_opaque_ptr->WasInterrupted() : false); +} + const char *SBCommandInterpreter::GetIOHandlerControlSequence(char ch) { return (IsValid() ? m_opaque_ptr->GetDebugger() diff --git a/source/API/SBDebugger.cpp b/source/API/SBDebugger.cpp index 3cdb6bbfd5f99..d3294dab582de 100644 --- a/source/API/SBDebugger.cpp +++ b/source/API/SBDebugger.cpp @@ -26,6 +26,7 @@ #include "lldb/API/SBSourceManager.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBStringList.h" +#include "lldb/API/SBStructuredData.h" #include "lldb/API/SBTarget.h" #include "lldb/API/SBThread.h" #include "lldb/API/SBTypeCategory.h" @@ -37,8 +38,10 @@ #include "lldb/API/SystemInitializerFull.h" #include "lldb/Core/Debugger.h" +#include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Core/StructuredDataImpl.h" #include "lldb/DataFormatters/DataVisualization.h" #include "lldb/Initialization/SystemLifetimeManager.h" #include "lldb/Interpreter/Args.h" @@ -69,7 +72,7 @@ static llvm::sys::DynamicLibrary LoadPlugin(const lldb::DebuggerSP &debugger_sp, // TODO: mangle this differently for your system - on OSX, the first // underscore needs to be removed and the second one stays LLDBCommandPluginInit init_func = - (LLDBCommandPluginInit)dynlib.getAddressOfSymbol( + (LLDBCommandPluginInit)(uintptr_t)dynlib.getAddressOfSymbol( "_ZN4lldb16PluginInitializeENS_10SBDebuggerE"); if (init_func) { if (init_func(debugger_sb)) @@ -619,6 +622,20 @@ SBTarget SBDebugger::CreateTarget(const char *filename) { return sb_target; } +SBTarget SBDebugger::GetDummyTarget() { + SBTarget sb_target; + if (m_opaque_sp) { + sb_target.SetSP(m_opaque_sp->GetDummyTarget()->shared_from_this()); + } + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + if (log) + log->Printf( + "SBDebugger(%p)::GetDummyTarget() => SBTarget(%p)", + static_cast<void *>(m_opaque_sp.get()), + static_cast<void *>(sb_target.GetSP().get())); + return sb_target; +} + bool SBDebugger::DeleteTarget(lldb::SBTarget &target) { bool result = false; if (m_opaque_sp) { @@ -677,8 +694,8 @@ SBTarget SBDebugger::FindTargetWithFileAndArch(const char *filename, SBTarget sb_target; if (m_opaque_sp && filename && filename[0]) { // No need to lock, the target list is thread safe - ArchSpec arch(arch_name, - m_opaque_sp->GetPlatformList().GetSelectedPlatform().get()); + ArchSpec arch = Platform::GetAugmentedArchSpec( + m_opaque_sp->GetPlatformList().GetSelectedPlatform().get(), arch_name); TargetSP target_sp( m_opaque_sp->GetTargetList().FindTargetWithExecutableAndArchitecture( FileSpec(filename, false), arch_name ? &arch : nullptr)); @@ -774,6 +791,67 @@ void SBDebugger::SetSelectedPlatform(SBPlatform &sb_platform) { sb_platform.GetName()); } +uint32_t SBDebugger::GetNumPlatforms() { + if (m_opaque_sp) { + // No need to lock, the platform list is thread safe + return m_opaque_sp->GetPlatformList().GetSize(); + } + return 0; +} + +SBPlatform SBDebugger::GetPlatformAtIndex(uint32_t idx) { + SBPlatform sb_platform; + if (m_opaque_sp) { + // No need to lock, the platform list is thread safe + sb_platform.SetSP(m_opaque_sp->GetPlatformList().GetAtIndex(idx)); + } + return sb_platform; +} + +uint32_t SBDebugger::GetNumAvailablePlatforms() { + uint32_t idx = 0; + while (true) { + if (!PluginManager::GetPlatformPluginNameAtIndex(idx)) { + break; + } + ++idx; + } + // +1 for the host platform, which should always appear first in the list. + return idx + 1; +} + +SBStructuredData SBDebugger::GetAvailablePlatformInfoAtIndex(uint32_t idx) { + SBStructuredData data; + auto platform_dict = llvm::make_unique<StructuredData::Dictionary>(); + llvm::StringRef name_str("name"), desc_str("description"); + + if (idx == 0) { + PlatformSP host_platform_sp(Platform::GetHostPlatform()); + platform_dict->AddStringItem( + name_str, host_platform_sp->GetPluginName().GetStringRef()); + platform_dict->AddStringItem( + desc_str, llvm::StringRef(host_platform_sp->GetDescription())); + } else if (idx > 0) { + const char *plugin_name = + PluginManager::GetPlatformPluginNameAtIndex(idx - 1); + if (!plugin_name) { + return data; + } + platform_dict->AddStringItem(name_str, llvm::StringRef(plugin_name)); + + const char *plugin_desc = + PluginManager::GetPlatformPluginDescriptionAtIndex(idx - 1); + if (!plugin_desc) { + return data; + } + platform_dict->AddStringItem(desc_str, llvm::StringRef(plugin_desc)); + } + + data.m_impl_up->SetObjectSP( + StructuredData::ObjectSP(platform_dict.release())); + return data; +} + void SBDebugger::DispatchInput(void *baton, const void *data, size_t data_len) { DispatchInput(data, data_len); } diff --git a/source/API/SBInstruction.cpp b/source/API/SBInstruction.cpp index 8b7deb7011be7..1cca8db2afe8d 100644 --- a/source/API/SBInstruction.cpp +++ b/source/API/SBInstruction.cpp @@ -14,15 +14,15 @@ #include "lldb/API/SBInstruction.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBTarget.h" - -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/EmulateInstruction.h" #include "lldb/Core/Module.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Host/HostInfo.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataExtractor.h" @@ -259,8 +259,7 @@ bool SBInstruction::EmulateWithFrame(lldb::SBFrame &frame, bool SBInstruction::DumpEmulation(const char *triple) { lldb::InstructionSP inst_sp(GetOpaque()); if (inst_sp && triple) { - lldb_private::ArchSpec arch(triple, NULL); - return inst_sp->DumpEmulation(arch); + return inst_sp->DumpEmulation(HostInfo::GetAugmentedArchSpec(triple)); } return false; } diff --git a/source/API/SBPlatform.cpp b/source/API/SBPlatform.cpp index 87cbc4537a3c8..7ec43f13021f3 100644 --- a/source/API/SBPlatform.cpp +++ b/source/API/SBPlatform.cpp @@ -12,11 +12,11 @@ #include "lldb/API/SBFileSpec.h" #include "lldb/API/SBLaunchInfo.h" #include "lldb/API/SBUnixSignals.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Host/File.h" #include "lldb/Interpreter/Args.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Status.h" #include "llvm/Support/FileSystem.h" diff --git a/source/API/SBProcess.cpp b/source/API/SBProcess.cpp index caf07dbe3ce88..e08a7f4b08e0b 100644 --- a/source/API/SBProcess.cpp +++ b/source/API/SBProcess.cpp @@ -1369,3 +1369,13 @@ lldb::SBMemoryRegionInfoList SBProcess::GetMemoryRegions() { } return sb_region_list; } + +lldb::SBProcessInfo SBProcess::GetProcessInfo() { + lldb::SBProcessInfo sb_proc_info; + ProcessSP process_sp(GetSP()); + ProcessInstanceInfo proc_info; + if (process_sp && process_sp->GetProcessInfo(proc_info)) { + sb_proc_info.SetProcessInfo(proc_info); + } + return sb_proc_info; +} diff --git a/source/API/SBProcessInfo.cpp b/source/API/SBProcessInfo.cpp new file mode 100644 index 0000000000000..38f6c1d1e699d --- /dev/null +++ b/source/API/SBProcessInfo.cpp @@ -0,0 +1,145 @@ +//===-- SBProcessInfo.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/API/SBProcessInfo.h" + +#include "lldb/API/SBFileSpec.h" +#include "lldb/Target/Process.h" + +using namespace lldb; +using namespace lldb_private; + +SBProcessInfo::SBProcessInfo() : m_opaque_ap() {} + +SBProcessInfo::SBProcessInfo(const SBProcessInfo &rhs) : m_opaque_ap() { + if (rhs.IsValid()) { + ref() = *rhs.m_opaque_ap; + } +} + +SBProcessInfo::~SBProcessInfo() {} + +SBProcessInfo &SBProcessInfo::operator=(const SBProcessInfo &rhs) { + if (this != &rhs) { + if (rhs.IsValid()) + ref() = *rhs.m_opaque_ap; + else + m_opaque_ap.reset(); + } + return *this; +} + +ProcessInstanceInfo &SBProcessInfo::ref() { + if (m_opaque_ap.get() == nullptr) { + m_opaque_ap.reset(new ProcessInstanceInfo()); + } + return *m_opaque_ap; +} + +void SBProcessInfo::SetProcessInfo(const ProcessInstanceInfo &proc_info_ref) { + ref() = proc_info_ref; +} + +bool SBProcessInfo::IsValid() const { return m_opaque_ap.get() != nullptr; } + +const char *SBProcessInfo::GetName() { + const char *name = nullptr; + if (m_opaque_ap) { + name = m_opaque_ap->GetName(); + } + return name; +} + +SBFileSpec SBProcessInfo::GetExecutableFile() { + SBFileSpec file_spec; + if (m_opaque_ap) { + file_spec.SetFileSpec(m_opaque_ap->GetExecutableFile()); + } + return file_spec; +} + +lldb::pid_t SBProcessInfo::GetProcessID() { + lldb::pid_t proc_id = LLDB_INVALID_PROCESS_ID; + if (m_opaque_ap) { + proc_id = m_opaque_ap->GetProcessID(); + } + return proc_id; +} + +uint32_t SBProcessInfo::GetUserID() { + uint32_t user_id = UINT32_MAX; + if (m_opaque_ap) { + user_id = m_opaque_ap->GetUserID(); + } + return user_id; +} + +uint32_t SBProcessInfo::GetGroupID() { + uint32_t group_id = UINT32_MAX; + if (m_opaque_ap) { + group_id = m_opaque_ap->GetGroupID(); + } + return group_id; +} + +bool SBProcessInfo::UserIDIsValid() { + bool is_valid = false; + if (m_opaque_ap) { + is_valid = m_opaque_ap->UserIDIsValid(); + } + return is_valid; +} + +bool SBProcessInfo::GroupIDIsValid() { + bool is_valid = false; + if (m_opaque_ap) { + is_valid = m_opaque_ap->GroupIDIsValid(); + } + return is_valid; +} + +uint32_t SBProcessInfo::GetEffectiveUserID() { + uint32_t user_id = UINT32_MAX; + if (m_opaque_ap) { + user_id = m_opaque_ap->GetEffectiveUserID(); + } + return user_id; +} + +uint32_t SBProcessInfo::GetEffectiveGroupID() { + uint32_t group_id = UINT32_MAX; + if (m_opaque_ap) { + group_id = m_opaque_ap->GetEffectiveGroupID(); + } + return group_id; +} + +bool SBProcessInfo::EffectiveUserIDIsValid() { + bool is_valid = false; + if (m_opaque_ap) { + is_valid = m_opaque_ap->EffectiveUserIDIsValid(); + } + return is_valid; +} + +bool SBProcessInfo::EffectiveGroupIDIsValid() { + bool is_valid = false; + if (m_opaque_ap) { + is_valid = m_opaque_ap->EffectiveGroupIDIsValid(); + } + return is_valid; +} + +lldb::pid_t SBProcessInfo::GetParentProcessID() { + lldb::pid_t proc_id = LLDB_INVALID_PROCESS_ID; + if (m_opaque_ap) { + proc_id = m_opaque_ap->GetParentProcessID(); + } + return proc_id; +} diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp index c706344ee4a39..2c1c6bcac71b6 100644 --- a/source/API/SBTarget.cpp +++ b/source/API/SBTarget.cpp @@ -31,7 +31,6 @@ #include "lldb/Core/Address.h" #include "lldb/Core/AddressResolver.h" #include "lldb/Core/AddressResolverName.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/Module.h" @@ -58,6 +57,7 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" #include "lldb/Target/TargetList.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/RegularExpression.h" @@ -414,16 +414,6 @@ lldb::SBProcess SBTarget::Attach(SBAttachInfo &sb_attach_info, SBError &error) { return sb_process; } -#if defined(__APPLE__) - -lldb::SBProcess SBTarget::AttachToProcessWithID(SBListener &listener, - ::pid_t pid, - lldb::SBError &error) { - return AttachToProcessWithID(listener, (lldb::pid_t)pid, error); -} - -#endif // #if defined(__APPLE__) - lldb::SBProcess SBTarget::AttachToProcessWithID( SBListener &listener, lldb::pid_t pid, // The process ID to attach to @@ -1097,11 +1087,35 @@ bool SBTarget::FindBreakpointsByName(const char *name, return true; } +void SBTarget::GetBreakpointNames(SBStringList &names) +{ + names.Clear(); + + TargetSP target_sp(GetSP()); + if (target_sp) { + std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex()); + + std::vector<std::string> name_vec; + target_sp->GetBreakpointNames(name_vec); + for (auto name : name_vec) + names.AppendString(name.c_str()); + } +} + +void SBTarget::DeleteBreakpointName(const char *name) +{ + TargetSP target_sp(GetSP()); + if (target_sp) { + std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex()); + target_sp->DeleteBreakpointName(ConstString(name)); + } +} + bool SBTarget::EnableAllBreakpoints() { TargetSP target_sp(GetSP()); if (target_sp) { std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex()); - target_sp->EnableAllBreakpoints(); + target_sp->EnableAllowedBreakpoints(); return true; } return false; @@ -1111,7 +1125,7 @@ bool SBTarget::DisableAllBreakpoints() { TargetSP target_sp(GetSP()); if (target_sp) { std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex()); - target_sp->DisableAllBreakpoints(); + target_sp->DisableAllowedBreakpoints(); return true; } return false; @@ -1121,7 +1135,7 @@ bool SBTarget::DeleteAllBreakpoints() { TargetSP target_sp(GetSP()); if (target_sp) { std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex()); - target_sp->RemoveAllBreakpoints(); + target_sp->RemoveAllowedBreakpoints(); return true; } return false; @@ -1428,8 +1442,8 @@ lldb::SBModule SBTarget::AddModule(const char *path, const char *triple, module_spec.GetUUID().SetFromCString(uuid_cstr); if (triple) - module_spec.GetArchitecture().SetTriple(triple, - target_sp->GetPlatform().get()); + module_spec.GetArchitecture() = Platform::GetAugmentedArchSpec( + target_sp->GetPlatform().get(), triple); else module_spec.GetArchitecture() = target_sp->GetArchitecture(); diff --git a/source/API/SBType.cpp b/source/API/SBType.cpp index e2ef07cf5c478..80d48754c89b2 100644 --- a/source/API/SBType.cpp +++ b/source/API/SBType.cpp @@ -415,21 +415,31 @@ uint32_t SBType::GetNumberOfTemplateArguments() { } lldb::SBType SBType::GetTemplateArgumentType(uint32_t idx) { - if (IsValid()) { - TemplateArgumentKind kind = eTemplateArgumentKindNull; - CompilerType template_arg_type = - m_opaque_sp->GetCompilerType(false).GetTemplateArgument(idx, kind); - if (template_arg_type.IsValid()) - return SBType(template_arg_type); + if (!IsValid()) + return SBType(); + + CompilerType type; + switch(GetTemplateArgumentKind(idx)) { + case eTemplateArgumentKindType: + type = m_opaque_sp->GetCompilerType(false).GetTypeTemplateArgument(idx); + break; + case eTemplateArgumentKindIntegral: + type = m_opaque_sp->GetCompilerType(false) + .GetIntegralTemplateArgument(idx) + ->type; + break; + default: + break; } + if (type.IsValid()) + return SBType(type); return SBType(); } lldb::TemplateArgumentKind SBType::GetTemplateArgumentKind(uint32_t idx) { - TemplateArgumentKind kind = eTemplateArgumentKindNull; if (IsValid()) - m_opaque_sp->GetCompilerType(false).GetTemplateArgument(idx, kind); - return kind; + return m_opaque_sp->GetCompilerType(false).GetTemplateArgumentKind(idx); + return eTemplateArgumentKindNull; } SBTypeList::SBTypeList() : m_opaque_ap(new TypeListImpl()) {} diff --git a/source/API/SystemInitializerFull.cpp b/source/API/SystemInitializerFull.cpp index c505f61e42a68..977ebe62353ec 100644 --- a/source/API/SystemInitializerFull.cpp +++ b/source/API/SystemInitializerFull.cpp @@ -42,6 +42,7 @@ #include "Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h" #include "Plugins/ABI/SysV-s390x/ABISysV_s390x.h" #include "Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h" +#include "Plugins/Architecture/Arm/ArchitectureArm.h" #include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h" #include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h" #include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h" @@ -50,9 +51,9 @@ #include "Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h" #include "Plugins/Instruction/ARM64/EmulateInstructionARM64.h" #include "Plugins/InstrumentationRuntime/ASan/ASanRuntime.h" +#include "Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.h" #include "Plugins/InstrumentationRuntime/TSan/TSanRuntime.h" #include "Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.h" -#include "Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.h" #include "Plugins/JITLoader/GDB/JITLoaderGDB.h" #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" #include "Plugins/Language/Go/GoLanguage.h" @@ -304,6 +305,9 @@ void SystemInitializerFull::Initialize() { ABISysV_mips::Initialize(); ABISysV_mips64::Initialize(); ABISysV_s390x::Initialize(); + + ArchitectureArm::Initialize(); + DisassemblerLLVMC::Initialize(); JITLoaderGDB::Initialize(); diff --git a/source/Breakpoint/Breakpoint.cpp b/source/Breakpoint/Breakpoint.cpp index 17c104ba0c600..3f6c63e1e5ba1 100644 --- a/source/Breakpoint/Breakpoint.cpp +++ b/source/Breakpoint/Breakpoint.cpp @@ -53,7 +53,7 @@ Breakpoint::Breakpoint(Target &target, SearchFilterSP &filter_sp, bool resolve_indirect_symbols) : m_being_created(true), m_hardware(hardware), m_target(target), m_filter_sp(filter_sp), m_resolver_sp(resolver_sp), - m_options_up(new BreakpointOptions()), m_locations(*this), + m_options_up(new BreakpointOptions(true)), m_locations(*this), m_resolve_indirect_symbols(resolve_indirect_symbols), m_hit_count(0) { m_being_created = false; } @@ -210,7 +210,7 @@ lldb::BreakpointSP Breakpoint::CreateFromStructuredData( llvm::StringRef name; Status error; success = names_array->GetItemAtIndexAsString(i, name); - result_sp->AddName(name, error); + target.AddNameToBreakpoint(result_sp, name.str().c_str(), error); } } @@ -348,6 +348,14 @@ void Breakpoint::SetOneShot(bool one_shot) { m_options_up->SetOneShot(one_shot); } +bool Breakpoint::IsAutoContinue() const { + return m_options_up->IsAutoContinue(); +} + +void Breakpoint::SetAutoContinue(bool auto_continue) { + m_options_up->SetAutoContinue(auto_continue); +} + void Breakpoint::SetThreadID(lldb::tid_t thread_id) { if (m_options_up->GetThreadSpec()->GetTID() == thread_id) return; @@ -447,6 +455,10 @@ bool Breakpoint::InvokeCallback(StoppointCallbackContext *context, BreakpointOptions *Breakpoint::GetOptions() { return m_options_up.get(); } +const BreakpointOptions *Breakpoint::GetOptions() const { + return m_options_up.get(); +} + void Breakpoint::ResolveBreakpoint() { if (m_resolver_sp) m_resolver_sp->ResolveBreakpoint(*m_filter_sp); @@ -833,18 +845,8 @@ size_t Breakpoint::GetNumResolvedLocations() const { size_t Breakpoint::GetNumLocations() const { return m_locations.GetSize(); } -bool Breakpoint::AddName(llvm::StringRef new_name, Status &error) { - if (new_name.empty()) - return false; - if (!BreakpointID::StringIsBreakpointName(new_name, error)) { - error.SetErrorStringWithFormatv("input name \"{0}\" not a breakpoint name.", - new_name); - return false; - } - if (!error.Success()) - return false; - - m_name_list.insert(new_name); +bool Breakpoint::AddName(llvm::StringRef new_name) { + m_name_list.insert(new_name.str().c_str()); return true; } diff --git a/source/Breakpoint/BreakpointID.cpp b/source/Breakpoint/BreakpointID.cpp index 112f7c0b51956..b801065468221 100644 --- a/source/Breakpoint/BreakpointID.cpp +++ b/source/Breakpoint/BreakpointID.cpp @@ -101,15 +101,24 @@ BreakpointID::ParseCanonicalReference(llvm::StringRef input) { bool BreakpointID::StringIsBreakpointName(llvm::StringRef str, Status &error) { error.Clear(); if (str.empty()) + { + error.SetErrorStringWithFormat("Empty breakpoint names are not allowed"); return false; + } // First character must be a letter or _ if (!isalpha(str[0]) && str[0] != '_') + { + error.SetErrorStringWithFormat("Breakpoint names must start with a " + "character or underscore: %s", + str.str().c_str()); return false; + } // Cannot contain ., -, or space. if (str.find_first_of(".- ") != llvm::StringRef::npos) { - error.SetErrorStringWithFormat("invalid breakpoint name: \"%s\"", + error.SetErrorStringWithFormat("Breakpoint names cannot contain " + "'.' or '-': \"%s\"", str.str().c_str()); return false; } diff --git a/source/Breakpoint/BreakpointIDList.cpp b/source/Breakpoint/BreakpointIDList.cpp index 7b461147a4e93..6d610d512f3b8 100644 --- a/source/Breakpoint/BreakpointIDList.cpp +++ b/source/Breakpoint/BreakpointIDList.cpp @@ -11,6 +11,7 @@ // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/lldb-enumerations.h" #include "lldb/Breakpoint/BreakpointIDList.h" #include "lldb/Breakpoint/Breakpoint.h" @@ -117,6 +118,8 @@ void BreakpointIDList::InsertStringArray(const char **string_array, void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target, bool allow_locations, + BreakpointName::Permissions + ::PermissionKinds purpose, CommandReturnObject &result, Args &new_args) { llvm::StringRef range_from; @@ -136,7 +139,6 @@ void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target, return; } - llvm::StringRef range_expr; Status error; std::tie(range_from, range_to) = @@ -302,14 +304,29 @@ void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target, } // Okay, now see if we found any names, and if we did, add them: - if (target && names_found.size()) { - for (BreakpointSP bkpt_sp : target->GetBreakpointList().Breakpoints()) { - for (std::string name : names_found) { - if (bkpt_sp->MatchesName(name.c_str())) { - StreamString canonical_id_str; - BreakpointID::GetCanonicalReference( - &canonical_id_str, bkpt_sp->GetID(), LLDB_INVALID_BREAK_ID); - new_args.AppendArgument(canonical_id_str.GetString()); + if (target && !names_found.empty()) { + Status error; + // Remove any names that aren't visible for this purpose: + auto iter = names_found.begin(); + while (iter != names_found.end()) { + BreakpointName *bp_name = target->FindBreakpointName(ConstString(*iter), + true, + error); + if (bp_name && !bp_name->GetPermission(purpose)) + iter = names_found.erase(iter); + else + iter++; + } + + if (!names_found.empty()) { + for (BreakpointSP bkpt_sp : target->GetBreakpointList().Breakpoints()) { + for (std::string name : names_found) { + if (bkpt_sp->MatchesName(name.c_str())) { + StreamString canonical_id_str; + BreakpointID::GetCanonicalReference( + &canonical_id_str, bkpt_sp->GetID(), LLDB_INVALID_BREAK_ID); + new_args.AppendArgument(canonical_id_str.GetString()); + } } } } diff --git a/source/Breakpoint/BreakpointList.cpp b/source/Breakpoint/BreakpointList.cpp index 15bcb34a3d85f..01ac59f0a903e 100644 --- a/source/Breakpoint/BreakpointList.cpp +++ b/source/Breakpoint/BreakpointList.cpp @@ -71,6 +71,13 @@ void BreakpointList::SetEnabledAll(bool enabled) { bp_sp->SetEnabled(enabled); } +void BreakpointList::SetEnabledAllowed(bool enabled) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + for (const auto &bp_sp : m_breakpoints) + if (bp_sp->AllowDisable()) + bp_sp->SetEnabled(enabled); +} + void BreakpointList::RemoveAll(bool notify) { std::lock_guard<std::recursive_mutex> guard(m_mutex); ClearAllBreakpointSites(); @@ -90,6 +97,32 @@ void BreakpointList::RemoveAll(bool notify) { m_breakpoints.erase(m_breakpoints.begin(), m_breakpoints.end()); } +void BreakpointList::RemoveAllowed(bool notify) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + + bp_collection::iterator pos, end = m_breakpoints.end(); + if (notify) { + for (pos = m_breakpoints.begin(); pos != end; ++pos) { + if(!(*pos)->AllowDelete()) + continue; + if ((*pos)->GetTarget().EventTypeHasListeners( + Target::eBroadcastBitBreakpointChanged)) { + (*pos)->GetTarget().BroadcastEvent( + Target::eBroadcastBitBreakpointChanged, + new Breakpoint::BreakpointEventData(eBreakpointEventTypeRemoved, + *pos)); + } + } + } + pos = m_breakpoints.begin(); + while ( pos != end) { + if((*pos)->AllowDelete()) + pos = m_breakpoints.erase(pos); + else + pos++; + } +} + class BreakpointIDMatches { public: BreakpointIDMatches(break_id_t break_id) : m_break_id(break_id) {} diff --git a/source/Breakpoint/BreakpointLocation.cpp b/source/Breakpoint/BreakpointLocation.cpp index ec8f141e8d38a..f59c334fe5c8a 100644 --- a/source/Breakpoint/BreakpointLocation.cpp +++ b/source/Breakpoint/BreakpointLocation.cpp @@ -58,6 +58,15 @@ lldb::addr_t BreakpointLocation::GetLoadAddress() const { return m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()); } +const BreakpointOptions * +BreakpointLocation::GetOptionsSpecifyingKind(BreakpointOptions::OptionKind kind) +const { + if (m_options_ap && m_options_ap->IsOptionSet(kind)) + return m_options_ap.get(); + else + return m_owner.GetOptions(); +} + Address &BreakpointLocation::GetAddress() { return m_address; } Breakpoint &BreakpointLocation::GetBreakpoint() { return m_owner; } @@ -84,6 +93,19 @@ void BreakpointLocation::SetEnabled(bool enabled) { : eBreakpointEventTypeDisabled); } +bool BreakpointLocation::IsAutoContinue() const { + if (m_options_ap + && m_options_ap->IsOptionSet(BreakpointOptions::eAutoContinue)) + return m_options_ap->IsAutoContinue(); + else + return m_owner.IsAutoContinue(); +} + +void BreakpointLocation::SetAutoContinue(bool auto_continue) { + GetLocationOptions()->SetAutoContinue(auto_continue); + SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged); +} + void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) { if (thread_id != LLDB_INVALID_THREAD_ID) GetLocationOptions()->SetThreadID(thread_id); @@ -97,8 +119,11 @@ void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) { } lldb::tid_t BreakpointLocation::GetThreadID() { - if (GetOptionsNoCreate()->GetThreadSpecNoCreate()) - return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(); + const ThreadSpec *thread_spec = + GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) + ->GetThreadSpecNoCreate(); + if (thread_spec) + return thread_spec->GetTID(); else return LLDB_INVALID_THREAD_ID; } @@ -116,8 +141,11 @@ void BreakpointLocation::SetThreadIndex(uint32_t index) { } uint32_t BreakpointLocation::GetThreadIndex() const { - if (GetOptionsNoCreate()->GetThreadSpecNoCreate()) - return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetIndex(); + const ThreadSpec *thread_spec = + GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) + ->GetThreadSpecNoCreate(); + if (thread_spec) + return thread_spec->GetIndex(); else return 0; } @@ -135,8 +163,11 @@ void BreakpointLocation::SetThreadName(const char *thread_name) { } const char *BreakpointLocation::GetThreadName() const { - if (GetOptionsNoCreate()->GetThreadSpecNoCreate()) - return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetName(); + const ThreadSpec *thread_spec = + GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) + ->GetThreadSpecNoCreate(); + if (thread_spec) + return thread_spec->GetName(); else return nullptr; } @@ -154,8 +185,11 @@ void BreakpointLocation::SetQueueName(const char *queue_name) { } const char *BreakpointLocation::GetQueueName() const { - if (GetOptionsNoCreate()->GetThreadSpecNoCreate()) - return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetQueueName(); + const ThreadSpec *thread_spec = + GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) + ->GetThreadSpecNoCreate(); + if (thread_spec) + return thread_spec->GetQueueName(); else return nullptr; } @@ -193,7 +227,8 @@ void BreakpointLocation::SetCondition(const char *condition) { } const char *BreakpointLocation::GetConditionText(size_t *hash) const { - return GetOptionsNoCreate()->GetConditionText(hash); + return GetOptionsSpecifyingKind(BreakpointOptions::eCondition) + ->GetConditionText(hash); } bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx, @@ -305,7 +340,8 @@ bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx, } uint32_t BreakpointLocation::GetIgnoreCount() { - return GetOptionsNoCreate()->GetIgnoreCount(); + return GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount) + ->GetIgnoreCount(); } void BreakpointLocation::SetIgnoreCount(uint32_t n) { @@ -335,26 +371,21 @@ bool BreakpointLocation::IgnoreCountShouldStop() { return true; } -const BreakpointOptions *BreakpointLocation::GetOptionsNoCreate() const { - if (m_options_ap.get() != nullptr) - return m_options_ap.get(); - else - return m_owner.GetOptions(); -} - BreakpointOptions *BreakpointLocation::GetLocationOptions() { // If we make the copy we don't copy the callbacks because that is potentially // expensive and we don't want to do that for the simple case where someone is // just disabling the location. if (m_options_ap.get() == nullptr) m_options_ap.reset( - BreakpointOptions::CopyOptionsNoCallback(*m_owner.GetOptions())); + new BreakpointOptions(false)); return m_options_ap.get(); } bool BreakpointLocation::ValidForThisThread(Thread *thread) { - return thread->MatchesSpec(GetOptionsNoCreate()->GetThreadSpecNoCreate()); + return thread + ->MatchesSpec(GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) + ->GetThreadSpecNoCreate()); } // RETURNS - true if we should stop at this breakpoint, false if we @@ -600,17 +631,20 @@ void BreakpointLocation::Dump(Stream *s) const { if (s == nullptr) return; + lldb::tid_t tid = GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) + ->GetThreadSpecNoCreate()->GetTID(); s->Printf( "BreakpointLocation %u: tid = %4.4" PRIx64 " load addr = 0x%8.8" PRIx64 " state = %s type = %s breakpoint " "hw_index = %i hit_count = %-4u ignore_count = %-4u", - GetID(), GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(), + GetID(), tid, (uint64_t)m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()), (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled", IsHardware() ? "hardware" : "software", GetHardwareIndex(), GetHitCount(), - GetOptionsNoCreate()->GetIgnoreCount()); + GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount) + ->GetIgnoreCount()); } void BreakpointLocation::SendBreakpointLocationChangedEvent( diff --git a/source/Breakpoint/BreakpointLocationList.cpp b/source/Breakpoint/BreakpointLocationList.cpp index b4cf0c38e9c28..1e4b4412a427b 100644 --- a/source/Breakpoint/BreakpointLocationList.cpp +++ b/source/Breakpoint/BreakpointLocationList.cpp @@ -15,11 +15,11 @@ #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" using namespace lldb; using namespace lldb_private; diff --git a/source/Breakpoint/BreakpointName.cpp b/source/Breakpoint/BreakpointName.cpp new file mode 100644 index 0000000000000..be4710d7849c8 --- /dev/null +++ b/source/Breakpoint/BreakpointName.cpp @@ -0,0 +1,91 @@ +//===-- Breakpoint.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details-> +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "llvm/Support/Casting.h" + +// Project includes +#include "lldb/Breakpoint/Breakpoint.h" +#include "lldb/Breakpoint/BreakpointOptions.h" +#include "lldb/Breakpoint/BreakpointLocationCollection.h" +#include "lldb/Breakpoint/BreakpointResolver.h" +#include "lldb/Breakpoint/BreakpointResolverFileLine.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Stream.h" +#include "lldb/Utility/StreamString.h" + +using namespace lldb; +using namespace lldb_private; + +const Flags::ValueType BreakpointName::Permissions::permissions_mask + [BreakpointName::Permissions::PermissionKinds::allPerms + 1] = { + (1u << 0), + (1u << 1), + (1u << 2), + (0x5u) +}; + +BreakpointName::BreakpointName(const ConstString &name, const Breakpoint &bkpt, + const char *help) : + m_name(name), m_options(bkpt.GetOptions()) +{ + SetHelp(help); +} + +bool BreakpointName::Permissions::GetDescription(Stream *s, + lldb::DescriptionLevel level) { + if (!AnySet()) + return false; + s->IndentMore(); + s->Indent(); + if (IsSet(listPerm)) + s->Printf("list: %s", GetAllowList() ? "allowed" : "disallowed"); + + if (IsSet(disablePerm)) + s->Printf("disable: %s", GetAllowDisable() ? "allowed" : "disallowed"); + + if (IsSet(deletePerm)) + s->Printf("delete: %s", GetAllowDelete() ? "allowed" : "disallowed"); + s->IndentLess(); + return true; +} + +bool BreakpointName::GetDescription(Stream *s, lldb::DescriptionLevel level) { + bool printed_any = false; + if (!m_help.empty()) + s->Printf("Help: %s\n", m_help.c_str()); + + if (GetOptions().AnySet()) + { + s->PutCString("Options: \n"); + s->IndentMore(); + s->Indent(); + GetOptions().GetDescription(s, level); + printed_any = true; + s->IndentLess(); + } + if (GetPermissions().AnySet()) + { + s->PutCString("Permissions: \n"); + s->IndentMore(); + s->Indent(); + GetPermissions().GetDescription(s, level); + printed_any = true; + s->IndentLess(); + } + return printed_any; +} + +void BreakpointName::ConfigureBreakpoint(lldb::BreakpointSP bp_sp) +{ + bp_sp->GetOptions()->CopyOverSetOptions(GetOptions()); + bp_sp->GetPermissions().MergeInto(GetPermissions()); +} diff --git a/source/Breakpoint/BreakpointOptions.cpp b/source/Breakpoint/BreakpointOptions.cpp index bef63cc0f222e..662b288794d3a 100644 --- a/source/Breakpoint/BreakpointOptions.cpp +++ b/source/Breakpoint/BreakpointOptions.cpp @@ -114,7 +114,8 @@ BreakpointOptions::CommandData::CreateFromStructuredData( const char *BreakpointOptions::g_option_names[( size_t)BreakpointOptions::OptionNames::LastOptionName]{ - "ConditionText", "IgnoreCount", "EnabledState", "OneShotState"}; + "ConditionText", "IgnoreCount", + "EnabledState", "OneShotState", "AutoContinue"}; bool BreakpointOptions::NullCallback(void *baton, StoppointCallbackContext *context, @@ -126,20 +127,30 @@ bool BreakpointOptions::NullCallback(void *baton, //---------------------------------------------------------------------- // BreakpointOptions constructor //---------------------------------------------------------------------- -BreakpointOptions::BreakpointOptions() +BreakpointOptions::BreakpointOptions(bool all_flags_set) : m_callback(BreakpointOptions::NullCallback), m_callback_baton_sp(), m_baton_is_command_baton(false), m_callback_is_synchronous(false), m_enabled(true), m_one_shot(false), m_ignore_count(0), m_thread_spec_ap(), - m_condition_text(), m_condition_text_hash(0) {} + m_condition_text(), m_condition_text_hash(0), m_auto_continue(false), + m_set_flags(0) { + if (all_flags_set) + m_set_flags.Set(~((Flags::ValueType) 0)); + } BreakpointOptions::BreakpointOptions(const char *condition, bool enabled, - int32_t ignore, bool one_shot) + int32_t ignore, bool one_shot, + bool auto_continue) : m_callback(nullptr), m_baton_is_command_baton(false), m_callback_is_synchronous(false), m_enabled(enabled), - m_one_shot(one_shot), m_ignore_count(ignore), m_condition_text(condition), - m_condition_text_hash(0) - -{} + m_one_shot(one_shot), m_ignore_count(ignore), + m_condition_text_hash(0), m_auto_continue(auto_continue) +{ + m_set_flags.Set(eEnabled | eIgnoreCount | eOneShot + | eAutoContinue); + if (condition && *condition != '\0') { + SetCondition(condition); + } +} //---------------------------------------------------------------------- // BreakpointOptions copy constructor @@ -149,7 +160,9 @@ BreakpointOptions::BreakpointOptions(const BreakpointOptions &rhs) m_baton_is_command_baton(rhs.m_baton_is_command_baton), m_callback_is_synchronous(rhs.m_callback_is_synchronous), m_enabled(rhs.m_enabled), m_one_shot(rhs.m_one_shot), - m_ignore_count(rhs.m_ignore_count), m_thread_spec_ap() { + m_ignore_count(rhs.m_ignore_count), m_thread_spec_ap(), + m_auto_continue(rhs.m_auto_continue), + m_set_flags(rhs.m_set_flags) { if (rhs.m_thread_spec_ap.get() != nullptr) m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get())); m_condition_text = rhs.m_condition_text; @@ -172,21 +185,62 @@ operator=(const BreakpointOptions &rhs) { m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get())); m_condition_text = rhs.m_condition_text; m_condition_text_hash = rhs.m_condition_text_hash; + m_auto_continue = rhs.m_auto_continue; + m_set_flags = rhs.m_set_flags; return *this; } -BreakpointOptions * -BreakpointOptions::CopyOptionsNoCallback(BreakpointOptions &orig) { - BreakpointHitCallback orig_callback = orig.m_callback; - lldb::BatonSP orig_callback_baton_sp = orig.m_callback_baton_sp; - bool orig_is_sync = orig.m_callback_is_synchronous; - - orig.ClearCallback(); - BreakpointOptions *ret_val = new BreakpointOptions(orig); - - orig.SetCallback(orig_callback, orig_callback_baton_sp, orig_is_sync); - - return ret_val; +void BreakpointOptions::CopyOverSetOptions(const BreakpointOptions &incoming) +{ + if (incoming.m_set_flags.Test(eEnabled)) + { + m_enabled = incoming.m_enabled; + m_set_flags.Set(eEnabled); + } + if (incoming.m_set_flags.Test(eOneShot)) + { + m_one_shot = incoming.m_one_shot; + m_set_flags.Set(eOneShot); + } + if (incoming.m_set_flags.Test(eCallback)) + { + m_callback = incoming.m_callback; + m_callback_baton_sp = incoming.m_callback_baton_sp; + m_callback_is_synchronous = incoming.m_callback_is_synchronous; + m_baton_is_command_baton = incoming.m_baton_is_command_baton; + m_set_flags.Set(eCallback); + } + if (incoming.m_set_flags.Test(eIgnoreCount)) + { + m_ignore_count = incoming.m_ignore_count; + m_set_flags.Set(eIgnoreCount); + } + if (incoming.m_set_flags.Test(eCondition)) + { + // If we're copying over an empty condition, mark it as unset. + if (incoming.m_condition_text.empty()) { + m_condition_text.clear(); + m_condition_text_hash = 0; + m_set_flags.Clear(eCondition); + } else { + m_condition_text = incoming.m_condition_text; + m_condition_text_hash = incoming.m_condition_text_hash; + m_set_flags.Set(eCondition); + } + } + if (incoming.m_set_flags.Test(eAutoContinue)) + { + m_auto_continue = incoming.m_auto_continue; + m_set_flags.Set(eAutoContinue); + } + if (incoming.m_set_flags.Test(eThreadSpec) && incoming.m_thread_spec_ap) + { + if (!m_thread_spec_ap) + m_thread_spec_ap.reset(new ThreadSpec(*incoming.m_thread_spec_ap.get())); + else + *m_thread_spec_ap.get() = *incoming.m_thread_spec_ap.get(); + m_set_flags.Set(eThreadSpec); + } } //---------------------------------------------------------------------- @@ -199,30 +253,65 @@ std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData( Status &error) { bool enabled = true; bool one_shot = false; + bool auto_continue = false; int32_t ignore_count = 0; - std::string condition_text; - - bool success = options_dict.GetValueForKeyAsBoolean( - GetKey(OptionNames::EnabledState), enabled); - if (!success) { - error.SetErrorStringWithFormat("%s key is not a boolean.", + llvm::StringRef condition_ref(""); + Flags set_options; + + const char *key = GetKey(OptionNames::EnabledState); + bool success; + if (key) { + success = options_dict.GetValueForKeyAsBoolean(key, enabled); + if (!success) { + error.SetErrorStringWithFormat("%s key is not a boolean.", GetKey(OptionNames::EnabledState)); - return nullptr; + return nullptr; + } + set_options.Set(eEnabled); } - success = options_dict.GetValueForKeyAsBoolean( - GetKey(OptionNames::OneShotState), one_shot); - if (!success) { - error.SetErrorStringWithFormat("%s key is not a boolean.", - GetKey(OptionNames::OneShotState)); - return nullptr; + key = GetKey(OptionNames::OneShotState); + if (key) { + success = options_dict.GetValueForKeyAsBoolean(key, one_shot); + if (!success) { + error.SetErrorStringWithFormat("%s key is not a boolean.", + GetKey(OptionNames::OneShotState)); + return nullptr; + } + set_options.Set(eOneShot); } - success = options_dict.GetValueForKeyAsInteger( - GetKey(OptionNames::IgnoreCount), ignore_count); - if (!success) { - error.SetErrorStringWithFormat("%s key is not an integer.", - GetKey(OptionNames::IgnoreCount)); - return nullptr; + + key = GetKey(OptionNames::AutoContinue); + if (key) { + success = options_dict.GetValueForKeyAsBoolean(key, auto_continue); + if (!success) { + error.SetErrorStringWithFormat("%s key is not a boolean.", + GetKey(OptionNames::AutoContinue)); + return nullptr; + } + set_options.Set(eAutoContinue); + } + + key = GetKey(OptionNames::IgnoreCount); + if (key) { + success = options_dict.GetValueForKeyAsInteger(key, ignore_count); + if (!success) { + error.SetErrorStringWithFormat("%s key is not an integer.", + GetKey(OptionNames::IgnoreCount)); + return nullptr; + } + set_options.Set(eIgnoreCount); + } + + key = GetKey(OptionNames::ConditionText); + if (key) { + success = options_dict.GetValueForKeyAsString(key, condition_ref); + if (!success) { + error.SetErrorStringWithFormat("%s key is not an string.", + GetKey(OptionNames::ConditionText)); + return nullptr; + } + set_options.Set(eCondition); } std::unique_ptr<CommandData> cmd_data_up; @@ -241,7 +330,8 @@ std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData( } auto bp_options = llvm::make_unique<BreakpointOptions>( - condition_text.c_str(), enabled, ignore_count, one_shot); + condition_ref.str().c_str(), enabled, + ignore_count, one_shot, auto_continue); if (cmd_data_up.get()) { if (cmd_data_up->interpreter == eScriptLanguageNone) bp_options->SetCommandDataCallback(cmd_data_up); @@ -293,14 +383,23 @@ std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData( StructuredData::ObjectSP BreakpointOptions::SerializeToStructuredData() { StructuredData::DictionarySP options_dict_sp( new StructuredData::Dictionary()); - options_dict_sp->AddBooleanItem(GetKey(OptionNames::EnabledState), m_enabled); - options_dict_sp->AddBooleanItem(GetKey(OptionNames::OneShotState), - m_one_shot); - options_dict_sp->AddIntegerItem(GetKey(OptionNames::IgnoreCount), - m_ignore_count); - options_dict_sp->AddStringItem(GetKey(OptionNames::ConditionText), - m_condition_text); - if (m_baton_is_command_baton) { + if (m_set_flags.Test(eEnabled)) + options_dict_sp->AddBooleanItem(GetKey(OptionNames::EnabledState), + m_enabled); + if (m_set_flags.Test(eOneShot)) + options_dict_sp->AddBooleanItem(GetKey(OptionNames::OneShotState), + m_one_shot); + if (m_set_flags.Test(eAutoContinue)) + options_dict_sp->AddBooleanItem(GetKey(OptionNames::AutoContinue), + m_auto_continue); + if (m_set_flags.Test(eIgnoreCount)) + options_dict_sp->AddIntegerItem(GetKey(OptionNames::IgnoreCount), + m_ignore_count); + if (m_set_flags.Test(eCondition)) + options_dict_sp->AddStringItem(GetKey(OptionNames::ConditionText), + m_condition_text); + + if (m_set_flags.Test(eCallback) && m_baton_is_command_baton) { auto cmd_baton = std::static_pointer_cast<CommandBaton>(m_callback_baton_sp); StructuredData::ObjectSP commands_sp = @@ -310,7 +409,7 @@ StructuredData::ObjectSP BreakpointOptions::SerializeToStructuredData() { BreakpointOptions::CommandData::GetSerializationKey(), commands_sp); } } - if (m_thread_spec_ap) { + if (m_set_flags.Test(eThreadSpec) && m_thread_spec_ap) { StructuredData::ObjectSP thread_spec_sp = m_thread_spec_ap->SerializeToStructuredData(); options_dict_sp->AddItem(ThreadSpec::GetSerializationKey(), thread_spec_sp); @@ -340,6 +439,7 @@ void BreakpointOptions::SetCallback(BreakpointHitCallback callback, m_callback = callback; m_callback_baton_sp = callback_baton_sp; m_baton_is_command_baton = false; + m_set_flags.Set(eCallback); } void BreakpointOptions::SetCallback( @@ -350,6 +450,7 @@ void BreakpointOptions::SetCallback( m_callback = callback; m_callback_baton_sp = callback_baton_sp; m_baton_is_command_baton = true; + m_set_flags.Set(eCallback); } void BreakpointOptions::ClearCallback() { @@ -357,6 +458,7 @@ void BreakpointOptions::ClearCallback() { m_callback_is_synchronous = false; m_callback_baton_sp.reset(); m_baton_is_command_baton = false; + m_set_flags.Clear(eCallback); } Baton *BreakpointOptions::GetBaton() { return m_callback_baton_sp.get(); } @@ -395,8 +497,12 @@ bool BreakpointOptions::GetCommandLineCallbacks(StringList &command_list) { } void BreakpointOptions::SetCondition(const char *condition) { - if (!condition) + if (!condition || condition[0] == '\0') { condition = ""; + m_set_flags.Clear(eCondition); + } + else + m_set_flags.Set(eCondition); m_condition_text.assign(condition); std::hash<std::string> hasher; @@ -427,11 +533,13 @@ ThreadSpec *BreakpointOptions::GetThreadSpec() { void BreakpointOptions::SetThreadID(lldb::tid_t thread_id) { GetThreadSpec()->SetTID(thread_id); + m_set_flags.Set(eThreadSpec); } void BreakpointOptions::SetThreadSpec( std::unique_ptr<ThreadSpec> &thread_spec_up) { m_thread_spec_ap = std::move(thread_spec_up); + m_set_flags.Set(eThreadSpec); } void BreakpointOptions::GetDescription(Stream *s, @@ -440,7 +548,7 @@ void BreakpointOptions::GetDescription(Stream *s, // print // anything if there are: - if (m_ignore_count != 0 || !m_enabled || m_one_shot || + if (m_ignore_count != 0 || !m_enabled || m_one_shot || m_auto_continue || (GetThreadSpecNoCreate() != nullptr && GetThreadSpecNoCreate()->HasSpecification())) { if (level == lldb::eDescriptionLevelVerbose) { @@ -460,6 +568,9 @@ void BreakpointOptions::GetDescription(Stream *s, if (m_one_shot) s->Printf("one-shot "); + if (m_auto_continue) + s->Printf("auto-continue "); + if (m_thread_spec_ap.get()) m_thread_spec_ap->GetDescription(s, level); @@ -520,6 +631,7 @@ void BreakpointOptions::SetCommandDataCallback( cmd_data->interpreter = eScriptLanguageNone; auto baton_sp = std::make_shared<CommandBaton>(std::move(cmd_data)); SetCallback(BreakpointOptions::BreakpointOptionsCallbackFunction, baton_sp); + m_set_flags.Set(eCallback); } bool BreakpointOptions::BreakpointOptionsCallbackFunction( @@ -562,3 +674,18 @@ bool BreakpointOptions::BreakpointOptionsCallbackFunction( } return ret_value; } + +void BreakpointOptions::Clear() +{ + m_set_flags.Clear(); + m_thread_spec_ap.release(); + m_one_shot = false; + m_ignore_count = 0; + m_auto_continue = false; + m_callback = nullptr; + m_callback_baton_sp.reset(); + m_baton_is_command_baton = false; + m_callback_is_synchronous = false; + m_enabled = false; + m_condition_text.clear(); +} diff --git a/source/Breakpoint/CMakeLists.txt b/source/Breakpoint/CMakeLists.txt index f6278528eab8a..f93d48579ad7d 100644 --- a/source/Breakpoint/CMakeLists.txt +++ b/source/Breakpoint/CMakeLists.txt @@ -6,6 +6,7 @@ add_lldb_library(lldbBreakpoint BreakpointLocation.cpp BreakpointLocationCollection.cpp BreakpointLocationList.cpp + BreakpointName.cpp BreakpointOptions.cpp BreakpointResolver.cpp BreakpointResolverAddress.cpp diff --git a/source/Commands/CommandCompletions.cpp b/source/Commands/CommandCompletions.cpp index fd84e1c4f8573..34cad970ff6ed 100644 --- a/source/Commands/CommandCompletions.cpp +++ b/source/Commands/CommandCompletions.cpp @@ -199,14 +199,14 @@ static int DiskFilesOrDirectories(const llvm::Twine &partial_name, // We have a match. - fs::file_status st; - if ((EC = Entry.status(st))) + llvm::ErrorOr<fs::basic_file_status> st = Entry.status(); + if (!st) continue; // If it's a symlink, then we treat it as a directory as long as the target // is a directory. - bool is_dir = fs::is_directory(st); - if (fs::is_symlink_file(st)) { + bool is_dir = fs::is_directory(*st); + if (fs::is_symlink_file(*st)) { fs::file_status target_st; if (!fs::status(Entry.path(), target_st)) is_dir = fs::is_directory(target_st); diff --git a/source/Commands/CommandObjectBreakpoint.cpp b/source/Commands/CommandObjectBreakpoint.cpp index 266864d1a1f0d..5a175d61060e3 100644 --- a/source/Commands/CommandObjectBreakpoint.cpp +++ b/source/Commands/CommandObjectBreakpoint.cpp @@ -45,6 +45,203 @@ static void AddBreakpointDescription(Stream *s, Breakpoint *bp, s->EOL(); } +//------------------------------------------------------------------------- +// Modifiable Breakpoint Options +//------------------------------------------------------------------------- +#pragma mark Modify::CommandOptions +static OptionDefinition g_breakpoint_modify_options[] = { + // clang-format off + { LLDB_OPT_SET_1, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." }, + { LLDB_OPT_SET_1, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." }, + { LLDB_OPT_SET_1, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument." }, + { LLDB_OPT_SET_1, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." }, + { LLDB_OPT_SET_1, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument." }, + { LLDB_OPT_SET_1, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument." }, + { LLDB_OPT_SET_1, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." }, + { LLDB_OPT_SET_1, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." }, + { LLDB_OPT_SET_2, false, "enable", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable the breakpoint." }, + { LLDB_OPT_SET_3, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint." }, + { LLDB_OPT_SET_4, false, "command", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCommand, "A command to run when the breakpoint is hit, can be provided more than once, the commands will get run in order left to right." }, + // clang-format on +}; +class lldb_private::BreakpointOptionGroup : public OptionGroup +{ +public: + BreakpointOptionGroup() : + OptionGroup(), + m_bp_opts(false) {} + + ~BreakpointOptionGroup() override = default; + + llvm::ArrayRef<OptionDefinition> GetDefinitions() override { + return llvm::makeArrayRef(g_breakpoint_modify_options); + } + + Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) override { + Status error; + const int short_option = g_breakpoint_modify_options[option_idx].short_option; + + switch (short_option) { + case 'c': + // Normally an empty breakpoint condition marks is as unset. + // But we need to say it was passed in. + m_bp_opts.SetCondition(option_arg.str().c_str()); + m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition); + break; + case 'C': + m_commands.push_back(option_arg); + break; + case 'd': + m_bp_opts.SetEnabled(false); + break; + case 'e': + m_bp_opts.SetEnabled(true); + break; + case 'G': { + bool value, success; + value = Args::StringToBoolean(option_arg, false, &success); + if (success) { + m_bp_opts.SetAutoContinue(value); + } else + error.SetErrorStringWithFormat( + "invalid boolean value '%s' passed for -G option", + option_arg.str().c_str()); + } + break; + case 'i': + { + uint32_t ignore_count; + if (option_arg.getAsInteger(0, ignore_count)) + error.SetErrorStringWithFormat("invalid ignore count '%s'", + option_arg.str().c_str()); + else + m_bp_opts.SetIgnoreCount(ignore_count); + } + break; + case 'o': { + bool value, success; + value = Args::StringToBoolean(option_arg, false, &success); + if (success) { + m_bp_opts.SetOneShot(value); + } else + error.SetErrorStringWithFormat( + "invalid boolean value '%s' passed for -o option", + option_arg.str().c_str()); + } break; + case 't': + { + lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID; + if (option_arg[0] != '\0') { + if (option_arg.getAsInteger(0, thread_id)) + error.SetErrorStringWithFormat("invalid thread id string '%s'", + option_arg.str().c_str()); + } + m_bp_opts.SetThreadID(thread_id); + } + break; + case 'T': + m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str()); + break; + case 'q': + m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str()); + break; + case 'x': + { + uint32_t thread_index = UINT32_MAX; + if (option_arg[0] != '\n') { + if (option_arg.getAsInteger(0, thread_index)) + error.SetErrorStringWithFormat("invalid thread index string '%s'", + option_arg.str().c_str()); + } + m_bp_opts.GetThreadSpec()->SetIndex(thread_index); + } + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_bp_opts.Clear(); + m_commands.clear(); + } + + Status OptionParsingFinished(ExecutionContext *execution_context) override { + if (!m_commands.empty()) + { + if (!m_commands.empty()) + { + auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>(); + + for (std::string &str : m_commands) + cmd_data->user_source.AppendString(str); + + cmd_data->stop_on_error = true; + m_bp_opts.SetCommandDataCallback(cmd_data); + } + } + return Status(); + } + + const BreakpointOptions &GetBreakpointOptions() + { + return m_bp_opts; + } + + std::vector<std::string> m_commands; + BreakpointOptions m_bp_opts; + +}; +static OptionDefinition g_breakpoint_dummy_options[] = { + // clang-format off + { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Act on Dummy breakpoints - i.e. breakpoints set before a file is provided, " + "which prime new targets." }, + // clang-format on +}; + +class BreakpointDummyOptionGroup : public OptionGroup +{ +public: + BreakpointDummyOptionGroup() : + OptionGroup() {} + + ~BreakpointDummyOptionGroup() override = default; + + llvm::ArrayRef<OptionDefinition> GetDefinitions() override { + return llvm::makeArrayRef(g_breakpoint_dummy_options); + } + + Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) override { + Status error; + const int short_option = g_breakpoint_modify_options[option_idx].short_option; + + switch (short_option) { + case 'D': + m_use_dummy = true; + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_use_dummy = false; + } + + bool m_use_dummy; + +}; + // If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to // update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately. #define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2) @@ -58,16 +255,7 @@ static OptionDefinition g_breakpoint_set_options[] = { // clang-format off { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the breakpoint only in this shared library. Can repeat this option " "multiple times to specify multiple shared libraries." }, - { LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." }, - { LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "The breakpoint is deleted the first time it causes a stop." }, - { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." }, - { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose indeX matches this argument." }, - { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." }, - { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this " - "argument." }, { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." }, - { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by " - "this argument." }, { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file in which to set this breakpoint. Note, by default " "lldb only looks for files that are #included if they use the standard include " "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are " @@ -125,8 +313,6 @@ static OptionDefinition g_breakpoint_set_options[] = { "If not set the target.language setting is used." }, { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "sKip the prologue if the breakpoint is at the beginning of a function. " "If not set the target.skip-prologue setting is used." }, - { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, " - "which prime new targets." }, { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." }, { LLDB_OPT_OFFSET_APPLIES, false, "address-slide", 'R', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddress, "Add the specified offset to whatever address(es) the breakpoint resolves to. " "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries." }, @@ -156,24 +342,30 @@ public: interpreter, "breakpoint set", "Sets a breakpoint or set of breakpoints in the executable.", "breakpoint set <cmd-options>"), - m_options() {} + m_bp_opts(), m_options() { + // We're picking up all the normal options, commands and disable. + m_all_options.Append(&m_bp_opts, + LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4, + LLDB_OPT_SET_ALL); + m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); + m_all_options.Append(&m_options); + m_all_options.Finalize(); + } ~CommandObjectBreakpointSet() override = default; - Options *GetOptions() override { return &m_options; } + Options *GetOptions() override { return &m_all_options; } - class CommandOptions : public Options { + class CommandOptions : public OptionGroup { public: CommandOptions() - : Options(), m_condition(), m_filenames(), m_line_num(0), m_column(0), + : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), m_column(0), m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone), m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(), - m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID), - m_thread_index(UINT32_MAX), m_thread_name(), m_queue_name(), m_catch_bp(false), m_throw_bp(true), m_hardware(false), m_exception_language(eLanguageTypeUnknown), m_language(lldb::eLanguageTypeUnknown), - m_skip_prologue(eLazyBoolCalculate), m_one_shot(false), + m_skip_prologue(eLazyBoolCalculate), m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {} ~CommandOptions() override = default; @@ -181,7 +373,7 @@ public: Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override { Status error; - const int short_option = m_getopt_table[option_idx].val; + const int short_option = g_breakpoint_set_options[option_idx].short_option; switch (short_option) { case 'a': { @@ -204,14 +396,6 @@ public: option_arg.str().c_str()); break; - case 'c': - m_condition.assign(option_arg); - break; - - case 'D': - m_use_dummy = true; - break; - case 'E': { LanguageType language = Language::GetLanguageTypeFromString(option_arg); @@ -255,7 +439,7 @@ public: m_func_names.push_back(option_arg); m_func_name_type_mask |= eFunctionNameTypeFull; break; - + case 'h': { bool success; m_catch_bp = Args::StringToBoolean(option_arg, true, &success); @@ -269,12 +453,6 @@ public: m_hardware = true; break; - case 'i': - if (option_arg.getAsInteger(0, m_ignore_count)) - error.SetErrorStringWithFormat("invalid ignore count '%s'", - option_arg.str().c_str()); - break; - case 'K': { bool success; bool value; @@ -347,10 +525,6 @@ public: m_offset_addr = tmp_offset_addr; } break; - case 'o': - m_one_shot = true; - break; - case 'O': m_exception_extra_args.AppendArgument("-O"); m_exception_extra_args.AppendArgument(option_arg); @@ -360,10 +534,6 @@ public: m_source_text_regexp.assign(option_arg); break; - case 'q': - m_queue_name.assign(option_arg); - break; - case 'r': m_func_regexp.assign(option_arg); break; @@ -377,16 +547,6 @@ public: m_func_name_type_mask |= eFunctionNameTypeSelector; break; - case 't': - if (option_arg.getAsInteger(0, m_thread_id)) - error.SetErrorStringWithFormat("invalid thread id string '%s'", - option_arg.str().c_str()); - break; - - case 'T': - m_thread_name.assign(option_arg); - break; - case 'w': { bool success; m_throw_bp = Args::StringToBoolean(option_arg, true, &success); @@ -396,12 +556,6 @@ public: option_arg.str().c_str()); } break; - case 'x': - if (option_arg.getAsInteger(0, m_thread_index)) - error.SetErrorStringWithFormat("invalid thread index string '%s'", - option_arg.str().c_str()); - break; - case 'X': m_source_regex_func_names.insert(option_arg); break; @@ -416,7 +570,6 @@ public: } void OptionParsingStarting(ExecutionContext *execution_context) override { - m_condition.clear(); m_filenames.Clear(); m_line_num = 0; m_column = 0; @@ -427,19 +580,12 @@ public: m_modules.Clear(); m_load_addr = LLDB_INVALID_ADDRESS; m_offset_addr = 0; - m_ignore_count = 0; - m_thread_id = LLDB_INVALID_THREAD_ID; - m_thread_index = UINT32_MAX; - m_thread_name.clear(); - m_queue_name.clear(); m_catch_bp = false; m_throw_bp = true; m_hardware = false; m_exception_language = eLanguageTypeUnknown; m_language = lldb::eLanguageTypeUnknown; m_skip_prologue = eLazyBoolCalculate; - m_one_shot = false; - m_use_dummy = false; m_breakpoint_names.clear(); m_all_files = false; m_exception_extra_args.Clear(); @@ -465,19 +611,12 @@ public: FileSpecList m_modules; lldb::addr_t m_load_addr; lldb::addr_t m_offset_addr; - uint32_t m_ignore_count; - lldb::tid_t m_thread_id; - uint32_t m_thread_index; - std::string m_thread_name; - std::string m_queue_name; bool m_catch_bp; bool m_throw_bp; bool m_hardware; // Request to use hardware breakpoints lldb::LanguageType m_exception_language; lldb::LanguageType m_language; LazyBool m_skip_prologue; - bool m_one_shot; - bool m_use_dummy; bool m_all_files; Args m_exception_extra_args; LazyBool m_move_to_nearest_code; @@ -486,7 +625,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); + Target *target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy); if (target == nullptr) { result.AppendError("Invalid target. Must set target before setting " @@ -521,7 +660,7 @@ protected: else if (m_options.m_exception_language != eLanguageTypeUnknown) break_type = eSetTypeException; - Breakpoint *bp = nullptr; + BreakpointSP bp_sp = nullptr; FileSpec module_spec; const bool internal = false; @@ -553,35 +692,32 @@ protected: // Only check for inline functions if LazyBool check_inlines = eLazyBoolCalculate; - bp = target - ->CreateBreakpoint(&(m_options.m_modules), file, - m_options.m_line_num, m_options.m_offset_addr, - check_inlines, m_options.m_skip_prologue, - internal, m_options.m_hardware, - m_options.m_move_to_nearest_code) - .get(); + bp_sp = target->CreateBreakpoint(&(m_options.m_modules), + file, + m_options.m_line_num, + m_options.m_offset_addr, + check_inlines, + m_options.m_skip_prologue, + internal, + m_options.m_hardware, + m_options.m_move_to_nearest_code); } break; case eSetTypeAddress: // Breakpoint by address { // If a shared library has been specified, make an lldb_private::Address - // with the library, and - // use that. That way the address breakpoint will track the load location - // of the library. + // with the library, and use that. That way the address breakpoint + // will track the load location of the library. size_t num_modules_specified = m_options.m_modules.GetSize(); if (num_modules_specified == 1) { const FileSpec *file_spec = m_options.m_modules.GetFileSpecPointerAtIndex(0); - bp = target - ->CreateAddressInModuleBreakpoint(m_options.m_load_addr, - internal, file_spec, - m_options.m_hardware) - .get(); + bp_sp = target->CreateAddressInModuleBreakpoint(m_options.m_load_addr, + internal, file_spec, + m_options.m_hardware); } else if (num_modules_specified == 0) { - bp = target - ->CreateBreakpoint(m_options.m_load_addr, internal, - m_options.m_hardware) - .get(); + bp_sp = target->CreateBreakpoint(m_options.m_load_addr, internal, + m_options.m_hardware); } else { result.AppendError("Only one shared library can be specified for " "address breakpoints."); @@ -597,13 +733,15 @@ protected: if (name_type_mask == 0) name_type_mask = eFunctionNameTypeAuto; - bp = target - ->CreateBreakpoint( - &(m_options.m_modules), &(m_options.m_filenames), - m_options.m_func_names, name_type_mask, m_options.m_language, - m_options.m_offset_addr, m_options.m_skip_prologue, internal, - m_options.m_hardware) - .get(); + bp_sp = target->CreateBreakpoint(&(m_options.m_modules), + &(m_options.m_filenames), + m_options.m_func_names, + name_type_mask, + m_options.m_language, + m_options.m_offset_addr, + m_options.m_skip_prologue, + internal, + m_options.m_hardware); } break; case eSetTypeFunctionRegexp: // Breakpoint by regular expression function @@ -620,12 +758,13 @@ protected: return false; } - bp = target - ->CreateFuncRegexBreakpoint( - &(m_options.m_modules), &(m_options.m_filenames), regexp, - m_options.m_language, m_options.m_skip_prologue, internal, - m_options.m_hardware) - .get(); + bp_sp = target->CreateFuncRegexBreakpoint(&(m_options.m_modules), + &(m_options.m_filenames), + regexp, + m_options.m_language, + m_options.m_skip_prologue, + internal, + m_options.m_hardware); } break; case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. @@ -654,26 +793,30 @@ protected: result.SetStatus(eReturnStatusFailed); return false; } - bp = target - ->CreateSourceRegexBreakpoint( - &(m_options.m_modules), &(m_options.m_filenames), - m_options.m_source_regex_func_names, regexp, internal, - m_options.m_hardware, m_options.m_move_to_nearest_code) - .get(); + bp_sp = + target->CreateSourceRegexBreakpoint(&(m_options.m_modules), + &(m_options.m_filenames), + m_options + .m_source_regex_func_names, + regexp, + internal, + m_options.m_hardware, + m_options.m_move_to_nearest_code); } break; case eSetTypeException: { Status precond_error; - bp = target - ->CreateExceptionBreakpoint( - m_options.m_exception_language, m_options.m_catch_bp, - m_options.m_throw_bp, internal, - &m_options.m_exception_extra_args, &precond_error) - .get(); + bp_sp = target->CreateExceptionBreakpoint(m_options.m_exception_language, + m_options.m_catch_bp, + m_options.m_throw_bp, + internal, + &m_options + .m_exception_extra_args, + &precond_error); if (precond_error.Fail()) { result.AppendErrorWithFormat( "Error setting extra exception arguments: %s", precond_error.AsCString()); - target->RemoveBreakpointByID(bp->GetID()); + target->RemoveBreakpointByID(bp_sp->GetID()); result.SetStatus(eReturnStatusFailed); return false; } @@ -683,64 +826,43 @@ protected: } // Now set the various options that were passed in: - if (bp) { - if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) - bp->SetThreadID(m_options.m_thread_id); - - if (m_options.m_thread_index != UINT32_MAX) - bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index); - - if (!m_options.m_thread_name.empty()) - bp->GetOptions()->GetThreadSpec()->SetName( - m_options.m_thread_name.c_str()); - - if (!m_options.m_queue_name.empty()) - bp->GetOptions()->GetThreadSpec()->SetQueueName( - m_options.m_queue_name.c_str()); - - if (m_options.m_ignore_count != 0) - bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count); - - if (!m_options.m_condition.empty()) - bp->GetOptions()->SetCondition(m_options.m_condition.c_str()); + if (bp_sp) { + bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); if (!m_options.m_breakpoint_names.empty()) { Status name_error; for (auto name : m_options.m_breakpoint_names) { - bp->AddName(name.c_str(), name_error); + target->AddNameToBreakpoint(bp_sp, name.c_str(), name_error); if (name_error.Fail()) { result.AppendErrorWithFormat("Invalid breakpoint name: %s", name.c_str()); - target->RemoveBreakpointByID(bp->GetID()); + target->RemoveBreakpointByID(bp_sp->GetID()); result.SetStatus(eReturnStatusFailed); return false; } } } - - bp->SetOneShot(m_options.m_one_shot); } - - if (bp) { + + if (bp_sp) { Stream &output_stream = result.GetOutputStream(); const bool show_locations = false; - bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, + bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, show_locations); if (target == m_interpreter.GetDebugger().GetDummyTarget()) output_stream.Printf("Breakpoint set in dummy target, will get copied " "into future targets.\n"); else { // Don't print out this warning for exception breakpoints. They can get - // set before the target - // is set, but we won't know how to actually set the breakpoint till we - // run. - if (bp->GetNumLocations() == 0 && break_type != eSetTypeException) { + // set before the target is set, but we won't know how to actually set + // the breakpoint till we run. + if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) { output_stream.Printf("WARNING: Unable to resolve breakpoint to any " "actual locations.\n"); } } result.SetStatus(eReturnStatusSuccessFinishResult); - } else if (!bp) { + } else if (!bp_sp) { result.AppendError("Breakpoint creation failed: No breakpoint created."); result.SetStatus(eReturnStatusFailed); } @@ -782,29 +904,15 @@ private: return true; } + BreakpointOptionGroup m_bp_opts; + BreakpointDummyOptionGroup m_dummy_options; CommandOptions m_options; + OptionGroupOptions m_all_options; }; //------------------------------------------------------------------------- // CommandObjectBreakpointModify //------------------------------------------------------------------------- - -#pragma mark Modify::CommandOptions -static OptionDefinition g_breakpoint_modify_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." }, - { LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." }, - { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument." }, - { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." }, - { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument." }, - { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument." }, - { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." }, - { LLDB_OPT_SET_1, false, "enable", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable the breakpoint." }, - { LLDB_OPT_SET_2, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint." }, - { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." }, - // clang-format on -}; - #pragma mark Modify class CommandObjectBreakpointModify : public CommandObjectParsed { @@ -825,148 +933,21 @@ public: // Add the entry for the first argument for this command to the object's // arguments vector. m_arguments.push_back(arg); + + m_options.Append(&m_bp_opts, + LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, + LLDB_OPT_SET_ALL); + m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); + m_options.Finalize(); } ~CommandObjectBreakpointModify() override = default; Options *GetOptions() override { return &m_options; } - class CommandOptions : public Options { - public: - CommandOptions() - : Options(), m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID), - m_thread_id_passed(false), m_thread_index(UINT32_MAX), - m_thread_index_passed(false), m_thread_name(), m_queue_name(), - m_condition(), m_one_shot(false), m_enable_passed(false), - m_enable_value(false), m_name_passed(false), m_queue_passed(false), - m_condition_passed(false), m_one_shot_passed(false), - m_use_dummy(false) {} - - ~CommandOptions() override = default; - - Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, - ExecutionContext *execution_context) override { - Status error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) { - case 'c': - m_condition = option_arg; - m_condition_passed = true; - break; - case 'd': - m_enable_passed = true; - m_enable_value = false; - break; - case 'D': - m_use_dummy = true; - break; - case 'e': - m_enable_passed = true; - m_enable_value = true; - break; - case 'i': - if (option_arg.getAsInteger(0, m_ignore_count)) - error.SetErrorStringWithFormat("invalid ignore count '%s'", - option_arg.str().c_str()); - break; - case 'o': { - bool value, success; - value = Args::StringToBoolean(option_arg, false, &success); - if (success) { - m_one_shot_passed = true; - m_one_shot = value; - } else - error.SetErrorStringWithFormat( - "invalid boolean value '%s' passed for -o option", - option_arg.str().c_str()); - } break; - case 't': - if (option_arg[0] == '\0') { - m_thread_id = LLDB_INVALID_THREAD_ID; - m_thread_id_passed = true; - } else { - if (option_arg.getAsInteger(0, m_thread_id)) - error.SetErrorStringWithFormat("invalid thread id string '%s'", - option_arg.str().c_str()); - else - m_thread_id_passed = true; - } - break; - case 'T': - m_thread_name = option_arg; - m_name_passed = true; - break; - case 'q': - m_queue_name = option_arg; - m_queue_passed = true; - break; - case 'x': - if (option_arg[0] == '\n') { - m_thread_index = UINT32_MAX; - m_thread_index_passed = true; - } else { - if (option_arg.getAsInteger(0, m_thread_index)) - error.SetErrorStringWithFormat("invalid thread index string '%s'", - option_arg.str().c_str()); - else - m_thread_index_passed = true; - } - break; - default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; - } - - return error; - } - - void OptionParsingStarting(ExecutionContext *execution_context) override { - m_ignore_count = 0; - m_thread_id = LLDB_INVALID_THREAD_ID; - m_thread_id_passed = false; - m_thread_index = UINT32_MAX; - m_thread_index_passed = false; - m_thread_name.clear(); - m_queue_name.clear(); - m_condition.clear(); - m_one_shot = false; - m_enable_passed = false; - m_queue_passed = false; - m_name_passed = false; - m_condition_passed = false; - m_one_shot_passed = false; - m_use_dummy = false; - } - - llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_breakpoint_modify_options); - } - - // Instance variables to hold the values for command options. - - uint32_t m_ignore_count; - lldb::tid_t m_thread_id; - bool m_thread_id_passed; - uint32_t m_thread_index; - bool m_thread_index_passed; - std::string m_thread_name; - std::string m_queue_name; - std::string m_condition; - bool m_one_shot; - bool m_enable_passed; - bool m_enable_value; - bool m_name_passed; - bool m_queue_passed; - bool m_condition_passed; - bool m_one_shot_passed; - bool m_use_dummy; - }; - protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); + Target *target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy); if (target == nullptr) { result.AppendError("Invalid target. No existing target or breakpoints."); result.SetStatus(eReturnStatusFailed); @@ -979,7 +960,8 @@ protected: BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids); + command, target, result, &valid_bp_ids, + BreakpointName::Permissions::PermissionKinds::disablePerm); if (result.Succeeded()) { const size_t count = valid_bp_ids.GetSize(); @@ -992,49 +974,12 @@ protected: if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { BreakpointLocation *location = bp->FindLocationByID(cur_bp_id.GetLocationID()).get(); - if (location) { - if (m_options.m_thread_id_passed) - location->SetThreadID(m_options.m_thread_id); - - if (m_options.m_thread_index_passed) - location->SetThreadIndex(m_options.m_thread_index); - - if (m_options.m_name_passed) - location->SetThreadName(m_options.m_thread_name.c_str()); - - if (m_options.m_queue_passed) - location->SetQueueName(m_options.m_queue_name.c_str()); - - if (m_options.m_ignore_count != 0) - location->SetIgnoreCount(m_options.m_ignore_count); - - if (m_options.m_enable_passed) - location->SetEnabled(m_options.m_enable_value); - - if (m_options.m_condition_passed) - location->SetCondition(m_options.m_condition.c_str()); - } + if (location) + location->GetLocationOptions() + ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); } else { - if (m_options.m_thread_id_passed) - bp->SetThreadID(m_options.m_thread_id); - - if (m_options.m_thread_index_passed) - bp->SetThreadIndex(m_options.m_thread_index); - - if (m_options.m_name_passed) - bp->SetThreadName(m_options.m_thread_name.c_str()); - - if (m_options.m_queue_passed) - bp->SetQueueName(m_options.m_queue_name.c_str()); - - if (m_options.m_ignore_count != 0) - bp->SetIgnoreCount(m_options.m_ignore_count); - - if (m_options.m_enable_passed) - bp->SetEnabled(m_options.m_enable_value); - - if (m_options.m_condition_passed) - bp->SetCondition(m_options.m_condition.c_str()); + bp->GetOptions() + ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); } } } @@ -1044,7 +989,9 @@ protected: } private: - CommandOptions m_options; + BreakpointOptionGroup m_bp_opts; + BreakpointDummyOptionGroup m_dummy_opts; + OptionGroupOptions m_options; }; //------------------------------------------------------------------------- @@ -1093,7 +1040,7 @@ protected: if (command.empty()) { // No breakpoint selected; enable all currently set breakpoints. - target->EnableAllBreakpoints(); + target->EnableAllowedBreakpoints(); result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64 " breakpoints)\n", (uint64_t)num_breakpoints); @@ -1102,7 +1049,8 @@ protected: // Particular breakpoint selected; enable that breakpoint. BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids); + command, target, result, &valid_bp_ids, + BreakpointName::Permissions::PermissionKinds::disablePerm); if (result.Succeeded()) { int enable_count = 0; @@ -1206,7 +1154,7 @@ protected: if (command.empty()) { // No breakpoint selected; disable all currently set breakpoints. - target->DisableAllBreakpoints(); + target->DisableAllowedBreakpoints(); result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64 " breakpoints)\n", (uint64_t)num_breakpoints); @@ -1216,7 +1164,8 @@ protected: BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids); + command, target, result, &valid_bp_ids, + BreakpointName::Permissions::PermissionKinds::disablePerm); if (result.Succeeded()) { int disable_count = 0; @@ -1383,14 +1332,17 @@ protected: result.AppendMessage("Current breakpoints:"); for (size_t i = 0; i < num_breakpoints; ++i) { Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get(); - AddBreakpointDescription(&output_stream, breakpoint, m_options.m_level); + if (breakpoint->AllowList()) + AddBreakpointDescription(&output_stream, breakpoint, + m_options.m_level); } result.SetStatus(eReturnStatusSuccessFinishNoResult); } else { // Particular breakpoints selected; show info about that breakpoint. BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids); + command, target, result, &valid_bp_ids, + BreakpointName::Permissions::PermissionKinds::listPerm); if (result.Succeeded()) { for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) { @@ -1678,7 +1630,7 @@ protected: true)) { result.AppendMessage("Operation cancelled..."); } else { - target->RemoveAllBreakpoints(); + target->RemoveAllowedBreakpoints(); result.AppendMessageWithFormat( "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); @@ -1688,7 +1640,8 @@ protected: // Particular breakpoint selected; disable that breakpoint. BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids); + command, target, result, &valid_bp_ids, + BreakpointName::Permissions::PermissionKinds::deletePerm); if (result.Succeeded()) { int delete_count = 0; @@ -1734,9 +1687,10 @@ private: static OptionDefinition g_breakpoint_name_options[] = { // clang-format off - {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."}, - {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."}, - {LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, + {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."}, + {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."}, + {LLDB_OPT_SET_3, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, + {LLDB_OPT_SET_4, false, "help-string", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A help string describing the purpose of this name."}, // clang-format on }; class BreakpointNameOptionGroup : public OptionGroup { @@ -1762,7 +1716,6 @@ public: error.Success()) m_name.SetValueFromString(option_arg); break; - case 'B': if (m_breakpoint.SetValueFromString(option_arg).Fail()) error.SetErrorStringWithFormat( @@ -1775,6 +1728,9 @@ public: "unrecognized value \"%s\" for use-dummy", option_arg.str().c_str()); break; + case 'H': + m_help_string.SetValueFromString(option_arg); + break; default: error.SetErrorStringWithFormat("unrecognized short option '%c'", @@ -1789,11 +1745,200 @@ public: m_breakpoint.Clear(); m_use_dummy.Clear(); m_use_dummy.SetDefaultValue(false); + m_help_string.Clear(); } OptionValueString m_name; OptionValueUInt64 m_breakpoint; OptionValueBoolean m_use_dummy; + OptionValueString m_help_string; +}; + +static OptionDefinition g_breakpoint_access_options[] = { + // clang-format off + {LLDB_OPT_SET_1, false, "allow-list", 'L', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Determines whether the breakpoint will show up in break list if not referred to explicitly."}, + {LLDB_OPT_SET_2, false, "allow-disable", 'A', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Determines whether the breakpoint can be disabled by name or when all breakpoints are disabled."}, + {LLDB_OPT_SET_3, false, "allow-delete", 'D', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Determines whether the breakpoint can be deleted by name or when all breakpoints are deleted."}, + // clang-format on +}; + +class BreakpointAccessOptionGroup : public OptionGroup +{ +public: + BreakpointAccessOptionGroup() : + OptionGroup() + {} + + ~BreakpointAccessOptionGroup() override = default; + + llvm::ArrayRef<OptionDefinition> GetDefinitions() override { + return llvm::makeArrayRef(g_breakpoint_access_options); + } + Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) override { + Status error; + const int short_option + = g_breakpoint_access_options[option_idx].short_option; + + switch (short_option) { + case 'L': { + bool value, success; + value = Args::StringToBoolean(option_arg, false, &success); + if (success) { + m_permissions.SetAllowList(value); + } else + error.SetErrorStringWithFormat( + "invalid boolean value '%s' passed for -L option", + option_arg.str().c_str()); + } break; + case 'A': { + bool value, success; + value = Args::StringToBoolean(option_arg, false, &success); + if (success) { + m_permissions.SetAllowDisable(value); + } else + error.SetErrorStringWithFormat( + "invalid boolean value '%s' passed for -L option", + option_arg.str().c_str()); + } break; + case 'D': { + bool value, success; + value = Args::StringToBoolean(option_arg, false, &success); + if (success) { + m_permissions.SetAllowDelete(value); + } else + error.SetErrorStringWithFormat( + "invalid boolean value '%s' passed for -L option", + option_arg.str().c_str()); + } break; + + } + + return error; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + } + + const BreakpointName::Permissions &GetPermissions() const + { + return m_permissions; + } + BreakpointName::Permissions m_permissions; +}; + +class CommandObjectBreakpointNameConfigure : public CommandObjectParsed { +public: + CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "configure", "Configure the options for the breakpoint" + " name provided. " + "If you provide a breakpoint id, the options will be copied from " + "the breakpoint, otherwise only the options specified will be set " + "on the name.", + "breakpoint name configure <command-options> " + "<breakpoint-name-list>"), + m_bp_opts(), m_option_group() { + // Create the first variant for the first (and only) argument for this + // command. + CommandArgumentEntry arg1; + CommandArgumentData id_arg; + id_arg.arg_type = eArgTypeBreakpointName; + id_arg.arg_repetition = eArgRepeatOptional; + arg1.push_back(id_arg); + m_arguments.push_back(arg1); + + m_option_group.Append(&m_bp_opts, + LLDB_OPT_SET_ALL, + LLDB_OPT_SET_1); + m_option_group.Append(&m_access_options, + LLDB_OPT_SET_ALL, + LLDB_OPT_SET_ALL); + m_option_group.Append(&m_bp_id, + LLDB_OPT_SET_2|LLDB_OPT_SET_4, + LLDB_OPT_SET_ALL); + m_option_group.Finalize(); + } + + ~CommandObjectBreakpointNameConfigure() override = default; + + Options *GetOptions() override { return &m_option_group; } + +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + + const size_t argc = command.GetArgumentCount(); + if (argc == 0) { + result.AppendError("No names provided."); + result.SetStatus(eReturnStatusFailed); + return false; + } + + Target *target = + GetSelectedOrDummyTarget(false); + + if (target == nullptr) { + result.AppendError("Invalid target. No existing target or breakpoints."); + result.SetStatus(eReturnStatusFailed); + return false; + } + + std::unique_lock<std::recursive_mutex> lock; + target->GetBreakpointList().GetListMutex(lock); + + // Make a pass through first to see that all the names are legal. + for (auto &entry : command.entries()) { + Status error; + if (!BreakpointID::StringIsBreakpointName(entry.ref, error)) + { + result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s", + entry.c_str(), error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + // Now configure them, we already pre-checked the names so we don't need + // to check the error: + BreakpointSP bp_sp; + if (m_bp_id.m_breakpoint.OptionWasSet()) + { + lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value(); + bp_sp = target->GetBreakpointByID(bp_id); + if (!bp_sp) + { + result.AppendErrorWithFormatv("Could not find specified breakpoint {0}", + bp_id); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + + Status error; + for (auto &entry : command.entries()) { + ConstString name(entry.c_str()); + BreakpointName *bp_name = target->FindBreakpointName(name, true, error); + if (!bp_name) + continue; + if (m_bp_id.m_help_string.OptionWasSet()) + bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str()); + + if (bp_sp) + target->ConfigureBreakpointName(*bp_name, + *bp_sp->GetOptions(), + m_access_options.GetPermissions()); + else + target->ConfigureBreakpointName(*bp_name, + m_bp_opts.GetBreakpointOptions(), + m_access_options.GetPermissions()); + } + return true; + } + +private: + BreakpointNameOptionGroup m_bp_id; // Only using the id part of this. + BreakpointOptionGroup m_bp_opts; + BreakpointAccessOptionGroup m_access_options; + OptionGroupOptions m_option_group; }; class CommandObjectBreakpointNameAdd : public CommandObjectParsed { @@ -1851,7 +1996,8 @@ protected: // Particular breakpoint selected; disable that breakpoint. BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( - command, target, result, &valid_bp_ids); + command, target, result, &valid_bp_ids, + BreakpointName::Permissions::PermissionKinds::listPerm); if (result.Succeeded()) { if (valid_bp_ids.GetSize() == 0) { @@ -1860,13 +2006,14 @@ protected: return false; } size_t num_valid_ids = valid_bp_ids.GetSize(); + const char *bp_name = m_name_options.m_name.GetCurrentValue(); + Status error; // This error reports illegal names, but we've already + // checked that, so we don't need to check it again here. for (size_t index = 0; index < num_valid_ids; index++) { lldb::break_id_t bp_id = valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); - Status error; // We don't need to check the error here, since the option - // parser checked it... - bp_sp->AddName(m_name_options.m_name.GetCurrentValue(), error); + target->AddNameToBreakpoint(bp_sp, bp_name, error); } } @@ -1934,7 +2081,8 @@ protected: // Particular breakpoint selected; disable that breakpoint. BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( - command, target, result, &valid_bp_ids); + command, target, result, &valid_bp_ids, + BreakpointName::Permissions::PermissionKinds::deletePerm); if (result.Succeeded()) { if (valid_bp_ids.GetSize() == 0) { @@ -1942,12 +2090,13 @@ protected: result.SetStatus(eReturnStatusFailed); return false; } + ConstString bp_name(m_name_options.m_name.GetCurrentValue()); size_t num_valid_ids = valid_bp_ids.GetSize(); for (size_t index = 0; index < num_valid_ids; index++) { lldb::break_id_t bp_id = valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); - bp_sp->RemoveName(m_name_options.m_name.GetCurrentValue()); + target->RemoveNameFromBreakpoint(bp_sp, bp_name); } } @@ -1963,11 +2112,12 @@ class CommandObjectBreakpointNameList : public CommandObjectParsed { public: CommandObjectBreakpointNameList(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "list", - "List either the names for a breakpoint or the " - "breakpoints for a given name.", + "List either the names for a breakpoint or info " + "about a given name. With no arguments, lists all " + "names", "breakpoint name list <command-options>"), m_name_options(), m_option_group() { - m_option_group.Append(&m_name_options); + m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL); m_option_group.Finalize(); } @@ -1985,42 +2135,57 @@ protected: result.SetStatus(eReturnStatusFailed); return false; } - - if (m_name_options.m_name.OptionWasSet()) { - const char *name = m_name_options.m_name.GetCurrentValue(); - std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); - - BreakpointList &breakpoints = target->GetBreakpointList(); - for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { - if (bp_sp->MatchesName(name)) { + + + std::vector<std::string> name_list; + if (command.empty()) { + target->GetBreakpointNames(name_list); + } else { + for (const Args::ArgEntry &arg : command) + { + name_list.push_back(arg.c_str()); + } + } + + if (name_list.empty()) { + result.AppendMessage("No breakpoint names found."); + } else { + for (const std::string &name_str : name_list) { + const char *name = name_str.c_str(); + // First print out the options for the name: + Status error; + BreakpointName *bp_name = target->FindBreakpointName(ConstString(name), + false, + error); + if (bp_name) + { StreamString s; - bp_sp->GetDescription(&s, eDescriptionLevelBrief); - s.EOL(); - result.AppendMessage(s.GetString()); + result.AppendMessageWithFormat("Name: %s\n", name); + if (bp_name->GetDescription(&s, eDescriptionLevelFull)) + { + result.AppendMessage(s.GetString()); + } + + std::unique_lock<std::recursive_mutex> lock; + target->GetBreakpointList().GetListMutex(lock); + + BreakpointList &breakpoints = target->GetBreakpointList(); + bool any_set = false; + for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { + if (bp_sp->MatchesName(name)) { + StreamString s; + any_set = true; + bp_sp->GetDescription(&s, eDescriptionLevelBrief); + s.EOL(); + result.AppendMessage(s.GetString()); + } + } + if (!any_set) + result.AppendMessage("No breakpoints using this name."); + } else { + result.AppendMessageWithFormat("Name: %s not found.\n", name); } } - - } else if (m_name_options.m_breakpoint.OptionWasSet()) { - BreakpointSP bp_sp = target->GetBreakpointList().FindBreakpointByID( - m_name_options.m_breakpoint.GetCurrentValue()); - if (bp_sp) { - std::vector<std::string> names; - bp_sp->GetNames(names); - result.AppendMessage("Names:"); - for (auto name : names) - result.AppendMessageWithFormat(" %s\n", name.c_str()); - } else { - result.AppendErrorWithFormat( - "Could not find breakpoint %" PRId64 ".\n", - m_name_options.m_breakpoint.GetCurrentValue()); - result.SetStatus(eReturnStatusFailed); - return false; - } - } else { - result.SetError("Must specify -N or -B option to list."); - result.SetStatus(eReturnStatusFailed); - return false; } return true; } @@ -2045,10 +2210,13 @@ public: new CommandObjectBreakpointNameDelete(interpreter)); CommandObjectSP list_command_object( new CommandObjectBreakpointNameList(interpreter)); + CommandObjectSP configure_command_object( + new CommandObjectBreakpointNameConfigure(interpreter)); LoadSubCommand("add", add_command_object); LoadSubCommand("delete", delete_command_object); LoadSubCommand("list", list_command_object); + LoadSubCommand("configure", configure_command_object); } ~CommandObjectBreakpointName() override = default; @@ -2274,7 +2442,8 @@ protected: BreakpointIDList valid_bp_ids; if (!command.empty()) { CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( - command, target, result, &valid_bp_ids); + command, target, result, &valid_bp_ids, + BreakpointName::Permissions::PermissionKinds::listPerm); if (!result.Succeeded()) { result.SetStatus(eReturnStatusFailed); @@ -2359,7 +2528,10 @@ CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default; void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target, bool allow_locations, CommandReturnObject &result, - BreakpointIDList *valid_ids) { + BreakpointIDList *valid_ids, + BreakpointName::Permissions + ::PermissionKinds + purpose) { // args can be strings representing 1). integers (for breakpoint ids) // 2). the full breakpoint & location // canonical representation @@ -2393,8 +2565,8 @@ void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target, // all the breakpoint ids in the range, and shove all of those breakpoint id // strings into TEMP_ARGS. - BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations, - result, temp_args); + BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations, + purpose, result, temp_args); // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual // BreakpointIDList: diff --git a/source/Commands/CommandObjectBreakpoint.h b/source/Commands/CommandObjectBreakpoint.h index 6e14b8f876a01..5e1026a6b7eaf 100644 --- a/source/Commands/CommandObjectBreakpoint.h +++ b/source/Commands/CommandObjectBreakpoint.h @@ -18,11 +18,14 @@ // Other libraries and framework includes // Project includes +#include "lldb/lldb-private.h" +#include "lldb/Breakpoint/BreakpointName.h" #include "lldb/Core/Address.h" #include "lldb/Core/STLUtils.h" #include "lldb/Interpreter/CommandObjectMultiword.h" #include "lldb/Interpreter/Options.h" + namespace lldb_private { //------------------------------------------------------------------------- @@ -37,20 +40,26 @@ public: static void VerifyBreakpointOrLocationIDs(Args &args, Target *target, CommandReturnObject &result, - BreakpointIDList *valid_ids) { - VerifyIDs(args, target, true, result, valid_ids); + BreakpointIDList *valid_ids, + BreakpointName::Permissions + ::PermissionKinds purpose) { + VerifyIDs(args, target, true, result, valid_ids, purpose); } static void VerifyBreakpointIDs(Args &args, Target *target, CommandReturnObject &result, - BreakpointIDList *valid_ids) { - VerifyIDs(args, target, false, result, valid_ids); + BreakpointIDList *valid_ids, + BreakpointName::Permissions::PermissionKinds + purpose) { + VerifyIDs(args, target, false, result, valid_ids, purpose); } private: static void VerifyIDs(Args &args, Target *target, bool allow_locations, CommandReturnObject &result, - BreakpointIDList *valid_ids); + BreakpointIDList *valid_ids, + BreakpointName::Permissions::PermissionKinds + purpose); }; } // namespace lldb_private diff --git a/source/Commands/CommandObjectBreakpointCommand.cpp b/source/Commands/CommandObjectBreakpointCommand.cpp index de49119531076..170cb85131160 100644 --- a/source/Commands/CommandObjectBreakpointCommand.cpp +++ b/source/Commands/CommandObjectBreakpointCommand.cpp @@ -390,7 +390,8 @@ protected: BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids); + command, target, result, &valid_bp_ids, + BreakpointName::Permissions::PermissionKinds::listPerm); m_bp_options_vec.clear(); @@ -571,7 +572,8 @@ protected: BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids); + command, target, result, &valid_bp_ids, + BreakpointName::Permissions::PermissionKinds::listPerm); if (result.Succeeded()) { const size_t count = valid_bp_ids.GetSize(); @@ -662,7 +664,8 @@ protected: BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids); + command, target, result, &valid_bp_ids, + BreakpointName::Permissions::PermissionKinds::listPerm); if (result.Succeeded()) { const size_t count = valid_bp_ids.GetSize(); @@ -673,48 +676,49 @@ protected: target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); if (bp) { - const BreakpointOptions *bp_options = nullptr; + BreakpointLocationSP bp_loc_sp; if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { - BreakpointLocationSP bp_loc_sp( - bp->FindLocationByID(cur_bp_id.GetLocationID())); - if (bp_loc_sp) - bp_options = bp_loc_sp->GetOptionsNoCreate(); - else { + bp_loc_sp = bp->FindLocationByID(cur_bp_id.GetLocationID()); + if (!bp_loc_sp) + { result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); result.SetStatus(eReturnStatusFailed); return false; } - } else { - bp_options = bp->GetOptions(); } - if (bp_options) { - StreamString id_str; - BreakpointID::GetCanonicalReference(&id_str, - cur_bp_id.GetBreakpointID(), - cur_bp_id.GetLocationID()); - const Baton *baton = bp_options->GetBaton(); - if (baton) { - result.GetOutputStream().Printf("Breakpoint %s:\n", - id_str.GetData()); - result.GetOutputStream().IndentMore(); - baton->GetDescription(&result.GetOutputStream(), - eDescriptionLevelFull); - result.GetOutputStream().IndentLess(); - } else { - result.AppendMessageWithFormat( - "Breakpoint %s does not have an associated command.\n", - id_str.GetData()); - } + StreamString id_str; + BreakpointID::GetCanonicalReference(&id_str, + cur_bp_id.GetBreakpointID(), + cur_bp_id.GetLocationID()); + const Baton *baton = nullptr; + if (bp_loc_sp) + baton = bp_loc_sp + ->GetOptionsSpecifyingKind(BreakpointOptions::eCallback) + ->GetBaton(); + else + baton = bp->GetOptions()->GetBaton(); + + if (baton) { + result.GetOutputStream().Printf("Breakpoint %s:\n", + id_str.GetData()); + result.GetOutputStream().IndentMore(); + baton->GetDescription(&result.GetOutputStream(), + eDescriptionLevelFull); + result.GetOutputStream().IndentLess(); + } else { + result.AppendMessageWithFormat( + "Breakpoint %s does not have an associated command.\n", + id_str.GetData()); } - result.SetStatus(eReturnStatusSuccessFinishResult); - } else { - result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", - cur_bp_id.GetBreakpointID()); - result.SetStatus(eReturnStatusFailed); } + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", + cur_bp_id.GetBreakpointID()); + result.SetStatus(eReturnStatusFailed); } } } diff --git a/source/Commands/CommandObjectDisassemble.cpp b/source/Commands/CommandObjectDisassemble.cpp index 5d0f2417f992e..31c54b7d433b3 100644 --- a/source/Commands/CommandObjectDisassemble.cpp +++ b/source/Commands/CommandObjectDisassemble.cpp @@ -163,8 +163,7 @@ Status CommandObjectDisassemble::CommandOptions::SetOptionValue( auto target_sp = execution_context ? execution_context->GetTargetSP() : TargetSP(); auto platform_sp = target_sp ? target_sp->GetPlatform() : PlatformSP(); - if (!arch.SetTriple(option_arg, platform_sp.get())) - arch.SetTriple(option_arg); + arch = Platform::GetAugmentedArchSpec(platform_sp.get(), option_arg); } break; diff --git a/source/Commands/CommandObjectDisassemble.h b/source/Commands/CommandObjectDisassemble.h index 8ca390056dd86..af15d45eb76bc 100644 --- a/source/Commands/CommandObjectDisassemble.h +++ b/source/Commands/CommandObjectDisassemble.h @@ -10,13 +10,9 @@ #ifndef liblldb_CommandObjectDisassemble_h_ #define liblldb_CommandObjectDisassemble_h_ -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/Options.h" +#include "lldb/Utility/ArchSpec.h" namespace lldb_private { diff --git a/source/Commands/CommandObjectExpression.cpp b/source/Commands/CommandObjectExpression.cpp index b6e0016c88e49..01ca311115556 100644 --- a/source/Commands/CommandObjectExpression.cpp +++ b/source/Commands/CommandObjectExpression.cpp @@ -228,6 +228,16 @@ CommandObjectExpression::CommandObjectExpression( m_command_options(), m_expr_line_count(0), m_expr_lines() { SetHelpLong( R"( +Single and multi-line expressions: + +)" + " The expression provided on the command line must be a complete expression \ +with no newlines. To evaluate a multi-line expression, \ +hit a return after an empty expression, and lldb will enter the multi-line expression editor. \ +Hit return on an empty line to end the multi-line expression." + + R"( + Timeouts: )" @@ -256,6 +266,7 @@ from the stack with \"thread return -x\" or if you are still interested in the e you can issue the \"continue\" command and the expression evaluation will complete and the \ expression result will be available using the \"thread.completed-expression\" key in the thread \ format." + R"( Examples: diff --git a/source/Commands/CommandObjectFrame.h b/source/Commands/CommandObjectFrame.h index 875bcc944a384..3199399163df3 100644 --- a/source/Commands/CommandObjectFrame.h +++ b/source/Commands/CommandObjectFrame.h @@ -10,11 +10,6 @@ #ifndef liblldb_CommandObjectFrame_h_ #define liblldb_CommandObjectFrame_h_ -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Interpreter/CommandObjectMultiword.h" #include "lldb/Interpreter/Options.h" diff --git a/source/Commands/CommandObjectPlatform.cpp b/source/Commands/CommandObjectPlatform.cpp index 5fa851f584a75..8ed003767d588 100644 --- a/source/Commands/CommandObjectPlatform.cpp +++ b/source/Commands/CommandObjectPlatform.cpp @@ -302,7 +302,7 @@ protected: platform_sp->GetStatus(ostrm); result.SetStatus(eReturnStatusSuccessFinishResult); } else { - result.AppendError("no platform us currently selected\n"); + result.AppendError("no platform is currently selected\n"); result.SetStatus(eReturnStatusFailed); } return result.Succeeded(); @@ -1337,8 +1337,8 @@ protected: PlatformSP platform_sp = debugger_sp ? debugger_sp->GetPlatformList().GetSelectedPlatform() : PlatformSP(); - match_info.GetProcessInfo().GetArchitecture().SetTriple( - option_arg, platform_sp.get()); + match_info.GetProcessInfo().GetArchitecture() = + Platform::GetAugmentedArchSpec(platform_sp.get(), option_arg); } break; case 'n': diff --git a/source/Commands/CommandObjectSource.cpp b/source/Commands/CommandObjectSource.cpp index f3c92b9a28c05..066cc59c5c315 100644 --- a/source/Commands/CommandObjectSource.cpp +++ b/source/Commands/CommandObjectSource.cpp @@ -902,7 +902,7 @@ protected: // We don't care about the column here. const uint32_t column = 0; return target->GetSourceManager().DisplaySourceLinesWithLineNumbers( - start_file, line_no, 0, m_options.num_lines, column, "", + start_file, line_no, column, 0, m_options.num_lines, "", &result.GetOutputStream(), GetBreakpointLocations()); } else { result.AppendErrorWithFormat( @@ -1161,7 +1161,7 @@ protected: ? sc.line_entry.column : 0; target->GetSourceManager().DisplaySourceLinesWithLineNumbers( - sc.comp_unit, sc.line_entry.line, lines_to_back_up, column, + sc.comp_unit, sc.line_entry.line, column, lines_to_back_up, m_options.num_lines - lines_to_back_up, "->", &result.GetOutputStream(), GetBreakpointLocations()); result.SetStatus(eReturnStatusSuccessFinishResult); @@ -1283,8 +1283,9 @@ protected: m_options.num_lines = 10; const uint32_t column = 0; target->GetSourceManager().DisplaySourceLinesWithLineNumbers( - sc.comp_unit, m_options.start_line, 0, m_options.num_lines, - column, "", &result.GetOutputStream(), GetBreakpointLocations()); + sc.comp_unit, m_options.start_line, column, + 0, m_options.num_lines, + "", &result.GetOutputStream(), GetBreakpointLocations()); result.SetStatus(eReturnStatusSuccessFinishResult); } else { diff --git a/source/Commands/CommandObjectTarget.cpp b/source/Commands/CommandObjectTarget.cpp index a80acf19be2d4..c83061d8de740 100644 --- a/source/Commands/CommandObjectTarget.cpp +++ b/source/Commands/CommandObjectTarget.cpp @@ -52,6 +52,7 @@ #include "lldb/Utility/Timer.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/FormatAdapters.h" // C Includes // C++ Includes @@ -135,25 +136,6 @@ static uint32_t DumpTargetList(TargetList &target_list, return num_targets; } -// TODO: Remove this once llvm can pretty-print time points -static void DumpTimePoint(llvm::sys::TimePoint<> tp, Stream &s, uint32_t width) { -#ifndef LLDB_DISABLE_POSIX - char time_buf[32]; - time_t time = llvm::sys::toTimeT(tp); - char *time_cstr = ::ctime_r(&time, time_buf); - if (time_cstr) { - char *newline = ::strpbrk(time_cstr, "\n\r"); - if (newline) - *newline = '\0'; - if (width > 0) - s.Printf("%-*s", width, time_cstr); - else - s.PutCString(time_cstr); - } else if (width > 0) - s.Printf("%-*s", width, ""); -#endif -} - #pragma mark CommandObjectTargetCreate //------------------------------------------------------------------------- @@ -2053,6 +2035,8 @@ protected: result.GetOutputStream().EOL(); result.GetOutputStream().EOL(); } + if (m_interpreter.WasInterrupted()) + break; num_dumped++; DumpModuleSymtab( m_interpreter, result.GetOutputStream(), @@ -2081,6 +2065,8 @@ protected: result.GetOutputStream().EOL(); result.GetOutputStream().EOL(); } + if (m_interpreter.WasInterrupted()) + break; num_dumped++; DumpModuleSymtab(m_interpreter, result.GetOutputStream(), module, m_options.m_sort_order); @@ -2146,6 +2132,8 @@ protected: " modules.\n", (uint64_t)num_modules); for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { + if (m_interpreter.WasInterrupted()) + break; num_dumped++; DumpModuleSections( m_interpreter, result.GetOutputStream(), @@ -2167,6 +2155,8 @@ protected: FindModulesByName(target, arg_cstr, module_list, true); if (num_matches > 0) { for (size_t i = 0; i < num_matches; ++i) { + if (m_interpreter.WasInterrupted()) + break; Module *module = module_list.GetModulePointerAtIndex(i); if (module) { num_dumped++; @@ -2239,6 +2229,8 @@ protected: " modules.\n", (uint64_t)num_modules); for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) { + if (m_interpreter.WasInterrupted()) + break; if (DumpModuleSymbolVendor( result.GetOutputStream(), target_modules.GetModulePointerAtIndexUnlocked(image_idx))) @@ -2260,6 +2252,8 @@ protected: FindModulesByName(target, arg_cstr, module_list, true); if (num_matches > 0) { for (size_t i = 0; i < num_matches; ++i) { + if (m_interpreter.WasInterrupted()) + break; Module *module = module_list.GetModulePointerAtIndex(i); if (module) { if (DumpModuleSymbolVendor(result.GetOutputStream(), module)) @@ -2327,6 +2321,8 @@ protected: if (num_modules > 0) { uint32_t num_dumped = 0; for (uint32_t i = 0; i < num_modules; ++i) { + if (m_interpreter.WasInterrupted()) + break; if (DumpCompileUnitLineTable( m_interpreter, result.GetOutputStream(), target_modules.GetModulePointerAtIndexUnlocked(i), @@ -2572,7 +2568,7 @@ public: "Fullpath or basename for module to load.", ""), m_load_option(LLDB_OPT_SET_1, false, "load", 'l', "Write file contents to the memory.", false, true), - m_pc_option(LLDB_OPT_SET_1, false, "--set-pc-to-entry", 'p', + m_pc_option(LLDB_OPT_SET_1, false, "set-pc-to-entry", 'p', "Set PC to the entry point." " Only applicable with '--load' option.", false, true), @@ -3162,7 +3158,8 @@ protected: } break; case 'm': - DumpTimePoint(module->GetModificationTime(), strm, width); + strm.Format("{0:%c}", llvm::fmt_align(module->GetModificationTime(), + llvm::AlignStyle::Left, width)); break; case 'p': @@ -3969,7 +3966,8 @@ public: "Add a debug symbol file to one of the target's current modules by " "specifying a path to a debug symbols file, or using the options " "to specify a module to download symbols for.", - "target symbols add [<symfile>]", eCommandRequiresTarget), + "target symbols add <cmd-options> [<symfile>]", + eCommandRequiresTarget), m_option_group(), m_file_option( LLDB_OPT_SET_1, false, "shlib", 's', @@ -4289,18 +4287,22 @@ protected: if (uuid_option_set) { result.AppendError("specify either one or more paths to symbol files " "or use the --uuid option without arguments"); - } else if (file_option_set) { - result.AppendError("specify either one or more paths to symbol files " - "or use the --file option without arguments"); } else if (frame_option_set) { result.AppendError("specify either one or more paths to symbol files " "or use the --frame option without arguments"); + } else if (file_option_set && argc > 1) { + result.AppendError("specify at most one symbol file path when " + "--shlib option is set"); } else { PlatformSP platform_sp(target->GetPlatform()); for (auto &entry : args.entries()) { if (!entry.ref.empty()) { module_spec.GetSymbolFileSpec().SetFile(entry.ref, true); + if (file_option_set) { + module_spec.GetFileSpec() = + m_file_option.GetOptionValue().GetCurrentValue(); + } if (platform_sp) { FileSpec symfile_spec; if (platform_sp diff --git a/source/Commands/CommandObjectTarget.h b/source/Commands/CommandObjectTarget.h index 865534111eec5..643ce547dcb62 100644 --- a/source/Commands/CommandObjectTarget.h +++ b/source/Commands/CommandObjectTarget.h @@ -10,11 +10,6 @@ #ifndef liblldb_CommandObjectTarget_h_ #define liblldb_CommandObjectTarget_h_ -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Interpreter/CommandObjectMultiword.h" #include "lldb/Interpreter/Options.h" diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp index 6a933df43e149..b68aa920b5821 100644 --- a/source/Commands/CommandObjectThread.cpp +++ b/source/Commands/CommandObjectThread.cpp @@ -94,7 +94,7 @@ public: bool all_threads = false; if (command.GetArgumentCount() == 0) { Thread *thread = m_exe_ctx.GetThreadPtr(); - if (!HandleOneThread(thread->GetID(), result)) + if (!thread || !HandleOneThread(thread->GetID(), result)) return false; return result.Succeeded(); } else if (command.GetArgumentCount() == 1) { @@ -775,6 +775,12 @@ protected: else error = process->Resume(); + if (!error.Success()) { + result.AppendMessage(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + // There is a race condition where this thread will return up the call // stack to the main command handler // and show an (lldb) prompt before HandlePrivateEvent (from diff --git a/source/Core/Address.cpp b/source/Core/Address.cpp index 0c929c22f75f6..54b485ce03549 100644 --- a/source/Core/Address.cpp +++ b/source/Core/Address.cpp @@ -8,8 +8,6 @@ //===----------------------------------------------------------------------===// #include "lldb/Core/Address.h" - -#include "lldb/Core/ArchSpec.h" // for ArchSpec #include "lldb/Core/DumpDataExtractor.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" // for ModuleList diff --git a/source/Core/AddressRange.cpp b/source/Core/AddressRange.cpp index c1507797b374c..e125b693d6f64 100644 --- a/source/Core/AddressRange.cpp +++ b/source/Core/AddressRange.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "lldb/Core/AddressRange.h" -#include "lldb/Core/ArchSpec.h" // for ArchSpec #include "lldb/Core/Module.h" #include "lldb/Target/Target.h" #include "lldb/Utility/ConstString.h" // for ConstString diff --git a/source/Core/CMakeLists.txt b/source/Core/CMakeLists.txt index c345afb4064ad..cac56e29fc191 100644 --- a/source/Core/CMakeLists.txt +++ b/source/Core/CMakeLists.txt @@ -13,7 +13,6 @@ add_lldb_library(lldbCore AddressResolver.cpp AddressResolverFileLine.cpp AddressResolverName.cpp - ArchSpec.cpp Broadcaster.cpp Communication.cpp Debugger.cpp diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp index d42e4df56d8bc..a4d78151c75fd 100644 --- a/source/Core/Debugger.cpp +++ b/source/Core/Debugger.cpp @@ -1170,7 +1170,7 @@ TestPromptFormats (StackFrame *frame) return; StreamString s; - const char *prompt_format = + const char *prompt_format = "{addr = '${addr}'\n}" "{addr-file-or-load = '${addr-file-or-load}'\n}" "{current-pc-arrow = '${current-pc-arrow}'\n}" diff --git a/source/Core/DumpDataExtractor.cpp b/source/Core/DumpDataExtractor.cpp index c2a9115c30682..e564e86478fc1 100644 --- a/source/Core/DumpDataExtractor.cpp +++ b/source/Core/DumpDataExtractor.cpp @@ -272,6 +272,13 @@ lldb::offset_t lldb_private::DumpDataExtractor( case eFormatChar: case eFormatCharPrintable: case eFormatCharArray: { + // Reject invalid item_byte_size. + if (item_byte_size > 8) { + s->Printf("error: unsupported byte size (%" PRIu64 ") for char format", + (uint64_t)item_byte_size); + return offset; + } + // If we are only printing one character surround it with single // quotes if (item_count == 1 && item_format == eFormatChar) diff --git a/source/Core/FileSpecList.cpp b/source/Core/FileSpecList.cpp index a69f490f9aedd..5b0bdac654e13 100644 --- a/source/Core/FileSpecList.cpp +++ b/source/Core/FileSpecList.cpp @@ -49,7 +49,7 @@ void FileSpecList::Append(const FileSpec &file_spec) { // contained a copy of "file_spec". //------------------------------------------------------------------ bool FileSpecList::AppendIfUnique(const FileSpec &file_spec) { - collection::iterator pos, end = m_files.end(); + collection::iterator end = m_files.end(); if (find(m_files.begin(), end, file_spec) == end) { m_files.push_back(file_spec); return true; @@ -147,36 +147,5 @@ size_t FileSpecList::GetSize() const { return m_files.size(); } size_t FileSpecList::GetFilesMatchingPartialPath(const char *path, bool dir_okay, FileSpecList &matches) { -#if 0 // FIXME: Just sketching... - matches.Clear(); - using namespace llvm::sys::fs; - file_status stats; - if (status(path, stats, false)) - return 0; - if (exists(stats)) { - if (is_symlink_file(stats)) { - // Shouldn't there be a method that realpath's a file? - } - if (is_regular_file(stats) || (is_directory(stats) && dir_okay)) { - matches.Append(FileSpec(path)); - return 1; - } else if (is_directory(stats)) { - // Fill the match list with all the files in the directory: - } else { - return 0; - } - } else { - ConstString dir_name = path_spec.GetDirectory(); - ConstString file_name = GetFilename(); - if (dir_name == nullptr) - { - // Match files in the CWD. - } - else - { - // Match files in the given directory: - } - } -#endif return 0; } diff --git a/source/Core/FormatEntity.cpp b/source/Core/FormatEntity.cpp index 6002efe9244d9..0cb74cc7658da 100644 --- a/source/Core/FormatEntity.cpp +++ b/source/Core/FormatEntity.cpp @@ -11,7 +11,6 @@ #include "lldb/Core/Address.h" #include "lldb/Core/AddressRange.h" // for AddressRange -#include "lldb/Core/ArchSpec.h" // for ArchSpec #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/RegisterValue.h" // for RegisterValue @@ -42,6 +41,7 @@ #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/AnsiTerminal.h" +#include "lldb/Utility/ArchSpec.h" // for ArchSpec #include "lldb/Utility/ConstString.h" // for ConstString, oper... #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" // for Log diff --git a/source/Core/IOHandler.cpp b/source/Core/IOHandler.cpp index 194fec8a87984..103b5ecde94a8 100644 --- a/source/Core/IOHandler.cpp +++ b/source/Core/IOHandler.cpp @@ -1146,7 +1146,7 @@ public: const char *text = m_delegate_sp->WindowDelegateGetHelpText(); KeyHelp *key_help = m_delegate_sp->WindowDelegateGetKeyHelp(); if ((text && text[0]) || key_help) { - std::auto_ptr<HelpDialogDelegate> help_delegate_ap( + std::unique_ptr<HelpDialogDelegate> help_delegate_ap( new HelpDialogDelegate(text, key_help)); const size_t num_lines = help_delegate_ap->GetNumLines(); const size_t max_length = help_delegate_ap->GetMaxLineLength(); diff --git a/source/Core/Module.cpp b/source/Core/Module.cpp index aaae4700db350..8f80be45f1b06 100644 --- a/source/Core/Module.cpp +++ b/source/Core/Module.cpp @@ -129,43 +129,6 @@ Module *Module::GetAllocatedModuleAtIndex(size_t idx) { return nullptr; } -#if 0 -// These functions help us to determine if modules are still loaded, yet don't require that -// you have a command interpreter and can easily be called from an external debugger. -namespace lldb { - - void - ClearModuleInfo (void) - { - const bool mandatory = true; - ModuleList::RemoveOrphanSharedModules(mandatory); - } - - void - DumpModuleInfo (void) - { - Mutex::Locker locker (Module::GetAllocationModuleCollectionMutex()); - ModuleCollection &modules = GetModuleCollection(); - const size_t count = modules.size(); - printf ("%s: %" PRIu64 " modules:\n", LLVM_PRETTY_FUNCTION, (uint64_t)count); - for (size_t i = 0; i < count; ++i) - { - - StreamString strm; - Module *module = modules[i]; - const bool in_shared_module_list = ModuleList::ModuleIsInCache (module); - module->GetDescription(&strm, eDescriptionLevelFull); - printf ("%p: shared = %i, ref_count = %3u, module = %s\n", - module, - in_shared_module_list, - (uint32_t)module->use_count(), - strm.GetString().c_str()); - } - } -} - -#endif - Module::Module(const ModuleSpec &module_spec) : m_object_offset(0), m_file_has_changed(false), m_first_file_changed_log(false) { diff --git a/source/Core/ModuleList.cpp b/source/Core/ModuleList.cpp index b04299ead8042..3970052b7bf3f 100644 --- a/source/Core/ModuleList.cpp +++ b/source/Core/ModuleList.cpp @@ -8,8 +8,6 @@ //===----------------------------------------------------------------------===// #include "lldb/Core/ModuleList.h" - -#include "lldb/Core/ArchSpec.h" // for ArchSpec #include "lldb/Core/FileSpecList.h" // for FileSpecList #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" @@ -18,6 +16,7 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" // for SymbolContextList, SymbolCon... #include "lldb/Symbol/VariableList.h" +#include "lldb/Utility/ArchSpec.h" // for ArchSpec #include "lldb/Utility/ConstString.h" // for ConstString #include "lldb/Utility/Log.h" #include "lldb/Utility/Logging.h" // for GetLogIfAnyCategoriesSet diff --git a/source/Core/PluginManager.cpp b/source/Core/PluginManager.cpp index 9bb615b6a55e2..a49fbc3f90fef 100644 --- a/source/Core/PluginManager.cpp +++ b/source/Core/PluginManager.cpp @@ -275,6 +275,54 @@ PluginManager::GetABICreateCallbackForPluginName(const ConstString &name) { return nullptr; } +#pragma mark Architecture + +struct ArchitectureInstance { + ConstString name; + std::string description; + PluginManager::ArchitectureCreateInstance create_callback; +}; + +typedef std::vector<ArchitectureInstance> ArchitectureInstances; + +static std::mutex g_architecture_mutex; + +static ArchitectureInstances &GetArchitectureInstances() { + static ArchitectureInstances g_instances; + return g_instances; +} + +void PluginManager::RegisterPlugin(const ConstString &name, + llvm::StringRef description, + ArchitectureCreateInstance create_callback) { + std::lock_guard<std::mutex> guard(g_architecture_mutex); + GetArchitectureInstances().push_back({name, description, create_callback}); +} + +void PluginManager::UnregisterPlugin( + ArchitectureCreateInstance create_callback) { + std::lock_guard<std::mutex> guard(g_architecture_mutex); + auto &instances = GetArchitectureInstances(); + + for (auto pos = instances.begin(), end = instances.end(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return; + } + } + llvm_unreachable("Plugin not found"); +} + +std::unique_ptr<Architecture> +PluginManager::CreateArchitectureInstance(const ArchSpec &arch) { + std::lock_guard<std::mutex> guard(g_architecture_mutex); + for (const auto &instances : GetArchitectureInstances()) { + if (auto plugin_up = instances.create_callback(arch)) + return plugin_up; + } + return nullptr; +} + #pragma mark Disassembler struct DisassemblerInstance { diff --git a/source/Core/RegisterValue.cpp b/source/Core/RegisterValue.cpp index 28ce67e63dc2f..f64c14019cc62 100644 --- a/source/Core/RegisterValue.cpp +++ b/source/Core/RegisterValue.cpp @@ -539,6 +539,9 @@ bool RegisterValue::SignExtend(uint32_t sign_bitpos) { } bool RegisterValue::CopyValue(const RegisterValue &rhs) { + if (this == &rhs) + return rhs.m_type == eTypeInvalid ? false : true; + m_type = rhs.m_type; switch (m_type) { case eTypeInvalid: diff --git a/source/Core/Section.cpp b/source/Core/Section.cpp index 3b76dd361ff3f..c9faf9f891571 100644 --- a/source/Core/Section.cpp +++ b/source/Core/Section.cpp @@ -65,6 +65,8 @@ static const char *GetSectionTypeAsCString(lldb::SectionType sect_type) { return "dwarf-addr"; case eSectionTypeDWARFDebugAranges: return "dwarf-aranges"; + case eSectionTypeDWARFDebugCuIndex: + return "dwarf-cu-index"; case eSectionTypeDWARFDebugFrame: return "dwarf-frame"; case eSectionTypeDWARFDebugInfo: @@ -133,7 +135,7 @@ Section::Section(const ModuleSP &module_sp, ObjectFile *obj_file, m_file_offset(file_offset), m_file_size(file_size), m_log2align(log2align), m_children(), m_fake(false), m_encrypted(false), m_thread_specific(false), m_readable(false), m_writable(false), - m_executable(false), m_target_byte_size(target_byte_size) { + m_executable(false), m_relocated(false), m_target_byte_size(target_byte_size) { // printf ("Section::Section(%p): module=%p, sect_id = 0x%16.16" PRIx64 ", // addr=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), file [0x%16.16" PRIx64 " // - 0x%16.16" PRIx64 "), flags = 0x%8.8x, name = %s\n", @@ -155,7 +157,7 @@ Section::Section(const lldb::SectionSP &parent_section_sp, m_file_offset(file_offset), m_file_size(file_size), m_log2align(log2align), m_children(), m_fake(false), m_encrypted(false), m_thread_specific(false), m_readable(false), m_writable(false), - m_executable(false), m_target_byte_size(target_byte_size) { + m_executable(false), m_relocated(false), m_target_byte_size(target_byte_size) { // printf ("Section::Section(%p): module=%p, sect_id = 0x%16.16" PRIx64 ", // addr=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), file [0x%16.16" PRIx64 " // - 0x%16.16" PRIx64 "), flags = 0x%8.8x, name = %s.%s\n", @@ -390,7 +392,7 @@ lldb::offset_t Section::GetSectionData(void *dst, lldb::offset_t dst_len, return 0; } -lldb::offset_t Section::GetSectionData(DataExtractor §ion_data) const { +lldb::offset_t Section::GetSectionData(DataExtractor §ion_data) { if (m_obj_file) return m_obj_file->ReadSectionData(this, section_data); return 0; diff --git a/source/Core/Value.cpp b/source/Core/Value.cpp index 63385511edb66..d415f1b09eb79 100644 --- a/source/Core/Value.cpp +++ b/source/Core/Value.cpp @@ -10,7 +10,6 @@ #include "lldb/Core/Value.h" #include "lldb/Core/Address.h" // for Address -#include "lldb/Core/ArchSpec.h" // for ArchSpec #include "lldb/Core/Module.h" #include "lldb/Core/State.h" #include "lldb/Symbol/CompilerType.h" @@ -143,6 +142,9 @@ Type *Value::GetType() { } size_t Value::AppendDataToHostBuffer(const Value &rhs) { + if (this == &rhs) + return 0; + size_t curr_size = m_data_buffer.GetByteSize(); Status error; switch (rhs.GetValueType()) { @@ -379,31 +381,6 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data, } else address = LLDB_INVALID_ADDRESS; } - // else - // { - // ModuleSP exe_module_sp - // (target->GetExecutableModule()); - // if (exe_module_sp) - // { - // address = - // m_value.ULongLong(LLDB_INVALID_ADDRESS); - // if (address != LLDB_INVALID_ADDRESS) - // { - // if - // (exe_module_sp->ResolveFileAddress(address, - // file_so_addr)) - // { - // data.SetByteOrder(target->GetArchitecture().GetByteOrder()); - // data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); - // address_type = eAddressTypeFile; - // } - // else - // { - // address = LLDB_INVALID_ADDRESS; - // } - // } - // } - // } } else { error.SetErrorString("can't read load address (invalid process)"); } @@ -560,7 +537,7 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data, "trying to read from host address of 0."); return error; } - memcpy(dst, (uint8_t *)NULL + address, byte_size); + memcpy(dst, reinterpret_cast<uint8_t *>(address), byte_size); } else if ((address_type == eAddressTypeLoad) || (address_type == eAddressTypeFile)) { if (file_so_addr.IsValid()) { diff --git a/source/Core/ValueObjectDynamicValue.cpp b/source/Core/ValueObjectDynamicValue.cpp index bb39caa767eb9..0013d0dbf740f 100644 --- a/source/Core/ValueObjectDynamicValue.cpp +++ b/source/Core/ValueObjectDynamicValue.cpp @@ -8,9 +8,7 @@ //===----------------------------------------------------------------------===// #include "lldb/Core/ValueObjectDynamicValue.h" - -#include "lldb/Core/ArchSpec.h" // for ArchSpec -#include "lldb/Core/Scalar.h" // for Scalar, operator!= +#include "lldb/Core/Scalar.h" // for Scalar, operator!= #include "lldb/Core/Value.h" #include "lldb/Core/ValueObject.h" #include "lldb/Symbol/CompilerType.h" diff --git a/source/Core/ValueObjectMemory.cpp b/source/Core/ValueObjectMemory.cpp index 713751110dcef..e26900014c9da 100644 --- a/source/Core/ValueObjectMemory.cpp +++ b/source/Core/ValueObjectMemory.cpp @@ -8,9 +8,7 @@ //===----------------------------------------------------------------------===// #include "lldb/Core/ValueObjectMemory.h" - -#include "lldb/Core/ArchSpec.h" // for ArchSpec -#include "lldb/Core/Scalar.h" // for Scalar, operator!= +#include "lldb/Core/Scalar.h" // for Scalar, operator!= #include "lldb/Core/Value.h" #include "lldb/Core/ValueObject.h" #include "lldb/Symbol/Type.h" diff --git a/source/Core/ValueObjectVariable.cpp b/source/Core/ValueObjectVariable.cpp index 9b9e51a0abb87..8436ba529a54c 100644 --- a/source/Core/ValueObjectVariable.cpp +++ b/source/Core/ValueObjectVariable.cpp @@ -11,7 +11,6 @@ #include "lldb/Core/Address.h" // for Address #include "lldb/Core/AddressRange.h" // for AddressRange -#include "lldb/Core/ArchSpec.h" // for ArchSpec #include "lldb/Core/Module.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" // for Scalar, operator!= @@ -156,9 +155,8 @@ bool ValueObjectVariable::UpdateValue() { target); } Value old_value(m_value); - if (expr.Evaluate(&exe_ctx, nullptr, nullptr, nullptr, - loclist_base_load_addr, nullptr, nullptr, m_value, - &m_error)) { + if (expr.Evaluate(&exe_ctx, nullptr, loclist_base_load_addr, nullptr, + nullptr, m_value, &m_error)) { m_resolved_value = m_value; m_value.SetContext(Value::eContextTypeVariable, variable); diff --git a/source/Expression/DWARFExpression.cpp b/source/Expression/DWARFExpression.cpp index 592a30cdd7800..14011aece7c99 100644 --- a/source/Expression/DWARFExpression.cpp +++ b/source/Expression/DWARFExpression.cpp @@ -24,9 +24,6 @@ #include "lldb/Utility/StreamString.h" #include "lldb/Utility/VMRange.h" -#include "Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h" -#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h" - #include "lldb/Host/Host.h" #include "lldb/Utility/Endian.h" @@ -1245,23 +1242,21 @@ bool DWARFExpression::DumpLocationForAddress(Stream *s, } bool DWARFExpression::Evaluate(ExecutionContextScope *exe_scope, - ClangExpressionVariableList *expr_locals, - ClangExpressionDeclMap *decl_map, lldb::addr_t loclist_base_load_addr, const Value *initial_value_ptr, const Value *object_address_ptr, Value &result, Status *error_ptr) const { ExecutionContext exe_ctx(exe_scope); - return Evaluate(&exe_ctx, expr_locals, decl_map, nullptr, - loclist_base_load_addr, initial_value_ptr, object_address_ptr, - result, error_ptr); + return Evaluate(&exe_ctx, nullptr, loclist_base_load_addr, initial_value_ptr, + object_address_ptr, result, error_ptr); } -bool DWARFExpression::Evaluate( - ExecutionContext *exe_ctx, ClangExpressionVariableList *expr_locals, - ClangExpressionDeclMap *decl_map, RegisterContext *reg_ctx, - lldb::addr_t loclist_base_load_addr, const Value *initial_value_ptr, - const Value *object_address_ptr, Value &result, Status *error_ptr) const { +bool DWARFExpression::Evaluate(ExecutionContext *exe_ctx, + RegisterContext *reg_ctx, + lldb::addr_t loclist_base_load_addr, + const Value *initial_value_ptr, + const Value *object_address_ptr, Value &result, + Status *error_ptr) const { ModuleSP module_sp = m_module_wp.lock(); if (IsLocationList()) { @@ -1307,9 +1302,9 @@ bool DWARFExpression::Evaluate( if (length > 0 && lo_pc <= pc && pc < hi_pc) { return DWARFExpression::Evaluate( - exe_ctx, expr_locals, decl_map, reg_ctx, module_sp, m_data, - m_dwarf_cu, offset, length, m_reg_kind, initial_value_ptr, - object_address_ptr, result, error_ptr); + exe_ctx, reg_ctx, module_sp, m_data, m_dwarf_cu, offset, length, + m_reg_kind, initial_value_ptr, object_address_ptr, result, + error_ptr); } offset += length; } @@ -1321,14 +1316,12 @@ bool DWARFExpression::Evaluate( // Not a location list, just a single expression. return DWARFExpression::Evaluate( - exe_ctx, expr_locals, decl_map, reg_ctx, module_sp, m_data, m_dwarf_cu, 0, - m_data.GetByteSize(), m_reg_kind, initial_value_ptr, object_address_ptr, - result, error_ptr); + exe_ctx, reg_ctx, module_sp, m_data, m_dwarf_cu, 0, m_data.GetByteSize(), + m_reg_kind, initial_value_ptr, object_address_ptr, result, error_ptr); } bool DWARFExpression::Evaluate( - ExecutionContext *exe_ctx, ClangExpressionVariableList *expr_locals, - ClangExpressionDeclMap *decl_map, RegisterContext *reg_ctx, + ExecutionContext *exe_ctx, RegisterContext *reg_ctx, lldb::ModuleSP module_sp, const DataExtractor &opcodes, DWARFCompileUnit *dwarf_cu, const lldb::offset_t opcodes_offset, const lldb::offset_t opcodes_length, const lldb::RegisterKind reg_kind, diff --git a/source/Expression/IRExecutionUnit.cpp b/source/Expression/IRExecutionUnit.cpp index 363e6fe8678fd..be53f37e0bcc7 100644 --- a/source/Expression/IRExecutionUnit.cpp +++ b/source/Expression/IRExecutionUnit.cpp @@ -260,7 +260,6 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr, llvm::Triple triple(m_module->getTargetTriple()); llvm::Reloc::Model relocModel; - llvm::CodeModel::Model codeModel; if (triple.isOSBinFormatELF()) { relocModel = llvm::Reloc::Static; @@ -268,9 +267,6 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr, relocModel = llvm::Reloc::PIC_; } - // This will be small for 32-bit and large for 64-bit. - codeModel = llvm::CodeModel::JITDefault; - m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, &error); @@ -281,7 +277,6 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr, .setRelocationModel(relocModel) .setMCJITMemoryManager( std::unique_ptr<MemoryManager>(new MemoryManager(*this))) - .setCodeModel(codeModel) .setOptLevel(llvm::CodeGenOpt::Less); llvm::StringRef mArch; @@ -1114,6 +1109,7 @@ bool IRExecutionUnit::CommitOneAllocation(lldb::ProcessSP &process_sp, case lldb::eSectionTypeDWARFDebugAbbrev: case lldb::eSectionTypeDWARFDebugAddr: case lldb::eSectionTypeDWARFDebugAranges: + case lldb::eSectionTypeDWARFDebugCuIndex: case lldb::eSectionTypeDWARFDebugFrame: case lldb::eSectionTypeDWARFDebugInfo: case lldb::eSectionTypeDWARFDebugLine: diff --git a/source/Expression/IRInterpreter.cpp b/source/Expression/IRInterpreter.cpp index 6b5e22329af83..a809bff20039b 100644 --- a/source/Expression/IRInterpreter.cpp +++ b/source/Expression/IRInterpreter.cpp @@ -385,11 +385,6 @@ public: return ret; } - lldb::addr_t MallocPointer() { - return Malloc(m_target_data.getPointerSize(), - m_target_data.getPointerPrefAlignment()); - } - lldb::addr_t Malloc(llvm::Type *type) { lldb_private::Status alloc_error; diff --git a/source/Host/CMakeLists.txt b/source/Host/CMakeLists.txt index 1696e7eab6ea9..2b6f0e48a3f20 100644 --- a/source/Host/CMakeLists.txt +++ b/source/Host/CMakeLists.txt @@ -31,6 +31,7 @@ add_host_subdirectory(common common/SoftwareBreakpoint.cpp common/StringConvert.cpp common/Symbols.cpp + common/TaskPool.cpp common/TCPSocket.cpp common/Terminal.cpp common/ThreadLauncher.cpp diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp index 8248aa3c5118a..97581185ad9e6 100644 --- a/source/Host/common/Host.cpp +++ b/source/Host/common/Host.cpp @@ -48,10 +48,6 @@ // C++ Includes #include <csignal> -// Other libraries and framework includes -// Project includes - -#include "lldb/Core/ArchSpec.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/HostProcess.h" diff --git a/source/Host/common/HostInfoBase.cpp b/source/Host/common/HostInfoBase.cpp index a6c9e91a98e80..aff887f9f1d2e 100644 --- a/source/Host/common/HostInfoBase.cpp +++ b/source/Host/common/HostInfoBase.cpp @@ -9,11 +9,11 @@ #include "lldb/Host/Config.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/HostInfoBase.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" @@ -103,6 +103,14 @@ const ArchSpec &HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) { : g_fields->m_host_arch_32; } +llvm::Optional<HostInfoBase::ArchitectureKind> HostInfoBase::ParseArchitectureKind(llvm::StringRef kind) { + return llvm::StringSwitch<llvm::Optional<ArchitectureKind>>(kind) + .Case(LLDB_ARCH_DEFAULT, eArchKindDefault) + .Case(LLDB_ARCH_DEFAULT_32BIT, eArchKind32) + .Case(LLDB_ARCH_DEFAULT_64BIT, eArchKind64) + .Default(llvm::None); +} + bool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) { file_spec.Clear(); @@ -251,6 +259,27 @@ bool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) { return true; } +ArchSpec HostInfoBase::GetAugmentedArchSpec(llvm::StringRef triple) { + if (triple.empty()) + return ArchSpec(); + llvm::Triple normalized_triple(llvm::Triple::normalize(triple)); + if (!ArchSpec::ContainsOnlyArch(normalized_triple)) + return ArchSpec(triple); + + if (auto kind = HostInfo::ParseArchitectureKind(triple)) + return HostInfo::GetArchitecture(*kind); + + llvm::Triple host_triple(llvm::sys::getDefaultTargetTriple()); + + if (normalized_triple.getVendorName().empty()) + normalized_triple.setVendor(host_triple.getVendor()); + if (normalized_triple.getOSName().empty()) + normalized_triple.setOS(host_triple.getOS()); + if (normalized_triple.getEnvironmentName().empty()) + normalized_triple.setEnvironment(host_triple.getEnvironment()); + return ArchSpec(normalized_triple); +} + bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) { // To get paths related to LLDB we get the path to the executable that // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB", diff --git a/source/Host/common/MainLoop.cpp b/source/Host/common/MainLoop.cpp index d0e0d00a31511..6cbb5a8425623 100644 --- a/source/Host/common/MainLoop.cpp +++ b/source/Host/common/MainLoop.cpp @@ -28,6 +28,8 @@ #include <sys/event.h> #elif defined(LLVM_ON_WIN32) #include <winsock2.h> +#elif defined(__ANDROID__) +#include <sys/syscall.h> #else #include <poll.h> #endif @@ -38,10 +40,6 @@ #define POLL poll #endif -#ifdef __ANDROID__ -#define FORCE_PSELECT -#endif - #if SIGNAL_POLLING_UNSUPPORTED #ifdef LLVM_ON_WIN32 typedef int sigset_t; @@ -86,7 +84,7 @@ private: int num_events = -1; #else -#ifdef FORCE_PSELECT +#ifdef __ANDROID__ fd_set read_fd_set; #else std::vector<struct pollfd> read_fds; @@ -134,7 +132,7 @@ void MainLoop::RunImpl::ProcessEvents() { } #else MainLoop::RunImpl::RunImpl(MainLoop &loop) : loop(loop) { -#ifndef FORCE_PSELECT +#ifndef __ANDROID__ read_fds.reserve(loop.m_read_fds.size()); #endif } @@ -154,8 +152,14 @@ sigset_t MainLoop::RunImpl::get_sigmask() { #endif } -#ifdef FORCE_PSELECT +#ifdef __ANDROID__ Status MainLoop::RunImpl::Poll() { + // ppoll(2) is not supported on older all android versions. Also, older + // versions android (API <= 19) implemented pselect in a non-atomic way, as a + // combination of pthread_sigmask and select. This is not sufficient for us, + // as we rely on the atomicity to correctly implement signal polling, so we + // call the underlying syscall ourselves. + FD_ZERO(&read_fd_set); int nfds = 0; for (const auto &fd : loop.m_read_fds) { @@ -163,8 +167,19 @@ Status MainLoop::RunImpl::Poll() { nfds = std::max(nfds, fd.first + 1); } - sigset_t sigmask = get_sigmask(); - if (pselect(nfds, &read_fd_set, nullptr, nullptr, nullptr, &sigmask) == -1 && + union { + sigset_t set; + uint64_t pad; + } kernel_sigset; + memset(&kernel_sigset, 0, sizeof(kernel_sigset)); + kernel_sigset.set = get_sigmask(); + + struct { + void *sigset_ptr; + size_t sigset_len; + } extra_data = {&kernel_sigset, sizeof(kernel_sigset)}; + if (syscall(__NR_pselect6, nfds, &read_fd_set, nullptr, nullptr, nullptr, + &extra_data) == -1 && errno != EINTR) return Status(errno, eErrorTypePOSIX); @@ -193,7 +208,7 @@ Status MainLoop::RunImpl::Poll() { #endif void MainLoop::RunImpl::ProcessEvents() { -#ifdef FORCE_PSELECT +#ifdef __ANDROID__ // Collect first all readable file descriptors into a separate vector and then // iterate over it to invoke callbacks. Iterating directly over // loop.m_read_fds is not possible because the callbacks can modify the @@ -206,7 +221,7 @@ void MainLoop::RunImpl::ProcessEvents() { for (const auto &handle : fds) { #else for (const auto &fd : read_fds) { - if ((fd.revents & POLLIN) == 0) + if ((fd.revents & (POLLIN | POLLHUP)) == 0) continue; IOObject::WaitableHandle handle = fd.fd; #endif diff --git a/source/Host/common/NativeProcessProtocol.cpp b/source/Host/common/NativeProcessProtocol.cpp index b5b6e9d8b9239..1fcb11b8b6f5d 100644 --- a/source/Host/common/NativeProcessProtocol.cpp +++ b/source/Host/common/NativeProcessProtocol.cpp @@ -8,8 +8,6 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/common/NativeProcessProtocol.h" - -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/State.h" #include "lldb/Host/Host.h" @@ -90,23 +88,23 @@ bool NativeProcessProtocol::SetExitStatus(WaitStatus status, return true; } -NativeThreadProtocolSP NativeProcessProtocol::GetThreadAtIndex(uint32_t idx) { +NativeThreadProtocol *NativeProcessProtocol::GetThreadAtIndex(uint32_t idx) { std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); if (idx < m_threads.size()) - return m_threads[idx]; - return NativeThreadProtocolSP(); + return m_threads[idx].get(); + return nullptr; } -NativeThreadProtocolSP +NativeThreadProtocol * NativeProcessProtocol::GetThreadByIDUnlocked(lldb::tid_t tid) { - for (auto thread_sp : m_threads) { - if (thread_sp->GetID() == tid) - return thread_sp; + for (const auto &thread : m_threads) { + if (thread->GetID() == tid) + return thread.get(); } - return NativeThreadProtocolSP(); + return nullptr; } -NativeThreadProtocolSP NativeProcessProtocol::GetThreadByID(lldb::tid_t tid) { +NativeThreadProtocol *NativeProcessProtocol::GetThreadByID(lldb::tid_t tid) { std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); return GetThreadByIDUnlocked(tid); } @@ -116,14 +114,6 @@ bool NativeProcessProtocol::IsAlive() const { m_state != eStateInvalid && m_state != eStateUnloaded; } -bool NativeProcessProtocol::GetByteOrder(lldb::ByteOrder &byte_order) const { - ArchSpec process_arch; - if (!GetArchitecture(process_arch)) - return false; - byte_order = process_arch.GetByteOrder(); - return true; -} - const NativeWatchpointList::WatchpointMap & NativeProcessProtocol::GetWatchpointMap() const { return m_watchpoint_list.GetWatchpointMap(); @@ -134,27 +124,16 @@ NativeProcessProtocol::GetHardwareDebugSupportInfo() const { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); // get any thread - NativeThreadProtocolSP thread_sp( + NativeThreadProtocol *thread( const_cast<NativeProcessProtocol *>(this)->GetThreadAtIndex(0)); - if (!thread_sp) { - if (log) - log->Warning("NativeProcessProtocol::%s (): failed to find a thread to " - "grab a NativeRegisterContext!", - __FUNCTION__); + if (!thread) { + LLDB_LOG(log, "failed to find a thread to grab a NativeRegisterContext!"); return llvm::None; } - NativeRegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); - if (!reg_ctx_sp) { - if (log) - log->Warning("NativeProcessProtocol::%s (): failed to get a " - "RegisterContextNativeProcess from the first thread!", - __FUNCTION__); - return llvm::None; - } - - return std::make_pair(reg_ctx_sp->NumSupportedHardwareBreakpoints(), - reg_ctx_sp->NumSupportedHardwareWatchpoints()); + NativeRegisterContext ®_ctx = thread->GetRegisterContext(); + return std::make_pair(reg_ctx.NumSupportedHardwareBreakpoints(), + reg_ctx.NumSupportedHardwareWatchpoints()); } Status NativeProcessProtocol::SetWatchpoint(lldb::addr_t addr, size_t size, @@ -175,7 +154,7 @@ Status NativeProcessProtocol::SetWatchpoint(lldb::addr_t addr, size_t size, // for. If one of the thread watchpoint setting operations fails, // back off and remove the watchpoint for all the threads that // were successfully set so we get back to a consistent state. - std::vector<NativeThreadProtocolSP> watchpoint_established_threads; + std::vector<NativeThreadProtocol *> watchpoint_established_threads; // Tell each thread to set a watchpoint. In the event that // hardware watchpoints are requested but the SetWatchpoint fails, @@ -184,40 +163,33 @@ Status NativeProcessProtocol::SetWatchpoint(lldb::addr_t addr, size_t size, // watchpoints available, some of the threads will fail to set // hardware watchpoints while software ones may be available. std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); - for (auto thread_sp : m_threads) { - assert(thread_sp && "thread list should not have a NULL thread!"); - if (!thread_sp) - continue; + for (const auto &thread : m_threads) { + assert(thread && "thread list should not have a NULL thread!"); Status thread_error = - thread_sp->SetWatchpoint(addr, size, watch_flags, hardware); + thread->SetWatchpoint(addr, size, watch_flags, hardware); if (thread_error.Fail() && hardware) { // Try software watchpoints since we failed on hardware watchpoint setting // and we may have just run out of hardware watchpoints. - thread_error = thread_sp->SetWatchpoint(addr, size, watch_flags, false); - if (thread_error.Success()) { - if (log) - log->Warning( - "hardware watchpoint requested but software watchpoint set"); - } + thread_error = thread->SetWatchpoint(addr, size, watch_flags, false); + if (thread_error.Success()) + LLDB_LOG(log, + "hardware watchpoint requested but software watchpoint set"); } if (thread_error.Success()) { // Remember that we set this watchpoint successfully in // case we need to clear it later. - watchpoint_established_threads.push_back(thread_sp); + watchpoint_established_threads.push_back(thread.get()); } else { // Unset the watchpoint for each thread we successfully // set so that we get back to a consistent state of "not // set" for the watchpoint. for (auto unwatch_thread_sp : watchpoint_established_threads) { Status remove_error = unwatch_thread_sp->RemoveWatchpoint(addr); - if (remove_error.Fail() && log) { - log->Warning("NativeProcessProtocol::%s (): RemoveWatchpoint failed " - "for pid=%" PRIu64 ", tid=%" PRIu64 ": %s", - __FUNCTION__, GetID(), unwatch_thread_sp->GetID(), - remove_error.AsCString()); - } + if (remove_error.Fail()) + LLDB_LOG(log, "RemoveWatchpoint failed for pid={0}, tid={1}: {2}", + GetID(), unwatch_thread_sp->GetID(), remove_error); } return thread_error; @@ -233,12 +205,10 @@ Status NativeProcessProtocol::RemoveWatchpoint(lldb::addr_t addr) { Status overall_error; std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); - for (auto thread_sp : m_threads) { - assert(thread_sp && "thread list should not have a NULL thread!"); - if (!thread_sp) - continue; + for (const auto &thread : m_threads) { + assert(thread && "thread list should not have a NULL thread!"); - const Status thread_error = thread_sp->RemoveWatchpoint(addr); + const Status thread_error = thread->RemoveWatchpoint(addr); if (thread_error.Fail()) { // Keep track of the first thread error if any threads // fail. We want to try to remove the watchpoint from @@ -277,20 +247,18 @@ Status NativeProcessProtocol::SetHardwareBreakpoint(lldb::addr_t addr, // set this hardware breakpoint. If any of the current process threads fails // to set this hardware breakpoint then roll back and remove this breakpoint // for all the threads that had already set it successfully. - std::vector<NativeThreadProtocolSP> breakpoint_established_threads; + std::vector<NativeThreadProtocol *> breakpoint_established_threads; // Request to set a hardware breakpoint for each of current process threads. std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); - for (auto thread_sp : m_threads) { - assert(thread_sp && "thread list should not have a NULL thread!"); - if (!thread_sp) - continue; + for (const auto &thread : m_threads) { + assert(thread && "thread list should not have a NULL thread!"); - Status thread_error = thread_sp->SetHardwareBreakpoint(addr, size); + Status thread_error = thread->SetHardwareBreakpoint(addr, size); if (thread_error.Success()) { // Remember that we set this breakpoint successfully in // case we need to clear it later. - breakpoint_established_threads.push_back(thread_sp); + breakpoint_established_threads.push_back(thread.get()); } else { // Unset the breakpoint for each thread we successfully // set so that we get back to a consistent state of "not @@ -298,12 +266,10 @@ Status NativeProcessProtocol::SetHardwareBreakpoint(lldb::addr_t addr, for (auto rollback_thread_sp : breakpoint_established_threads) { Status remove_error = rollback_thread_sp->RemoveHardwareBreakpoint(addr); - if (remove_error.Fail() && log) { - log->Warning("NativeProcessProtocol::%s (): RemoveHardwareBreakpoint" - " failed for pid=%" PRIu64 ", tid=%" PRIu64 ": %s", - __FUNCTION__, GetID(), rollback_thread_sp->GetID(), - remove_error.AsCString()); - } + if (remove_error.Fail()) + LLDB_LOG(log, + "RemoveHardwareBreakpoint failed for pid={0}, tid={1}: {2}", + GetID(), rollback_thread_sp->GetID(), remove_error); } return thread_error; @@ -324,12 +290,9 @@ Status NativeProcessProtocol::RemoveHardwareBreakpoint(lldb::addr_t addr) { Status error; std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); - for (auto thread_sp : m_threads) { - assert(thread_sp && "thread list should not have a NULL thread!"); - if (!thread_sp) - continue; - - error = thread_sp->RemoveHardwareBreakpoint(addr); + for (const auto &thread : m_threads) { + assert(thread && "thread list should not have a NULL thread!"); + error = thread->RemoveHardwareBreakpoint(addr); } // Also remove from hardware breakpoint map of current process. diff --git a/source/Host/common/NativeRegisterContext.cpp b/source/Host/common/NativeRegisterContext.cpp index 629b0247422d2..60eaebdc94cd2 100644 --- a/source/Host/common/NativeRegisterContext.cpp +++ b/source/Host/common/NativeRegisterContext.cpp @@ -19,9 +19,8 @@ using namespace lldb; using namespace lldb_private; -NativeRegisterContext::NativeRegisterContext(NativeThreadProtocol &thread, - uint32_t concrete_frame_idx) - : m_thread(thread), m_concrete_frame_idx(concrete_frame_idx) {} +NativeRegisterContext::NativeRegisterContext(NativeThreadProtocol &thread) + : m_thread(thread) {} //---------------------------------------------------------------------- // Destructor @@ -368,13 +367,8 @@ Status NativeRegisterContext::ReadRegisterValueFromMemory( // TODO: we might need to add a parameter to this function in case the byte // order of the memory data doesn't match the process. For now we are assuming // they are the same. - lldb::ByteOrder byte_order; - if (process.GetByteOrder(byte_order)) { - error.SetErrorString("NativeProcessProtocol::GetByteOrder () failed"); - return error; - } - - reg_value.SetFromMemoryData(reg_info, src, src_len, byte_order, error); + reg_value.SetFromMemoryData(reg_info, src, src_len, process.GetByteOrder(), + error); return error; } @@ -393,12 +387,8 @@ Status NativeRegisterContext::WriteRegisterValueToMemory( // order of the memory data doesn't match the process. For now we are // assuming // they are the same. - lldb::ByteOrder byte_order; - if (!process.GetByteOrder(byte_order)) - return Status("NativeProcessProtocol::GetByteOrder () failed"); - - const size_t bytes_copied = - reg_value.GetAsMemoryData(reg_info, dst, dst_len, byte_order, error); + const size_t bytes_copied = reg_value.GetAsMemoryData( + reg_info, dst, dst_len, process.GetByteOrder(), error); if (error.Success()) { if (bytes_copied == 0) { diff --git a/source/Host/common/NativeThreadProtocol.cpp b/source/Host/common/NativeThreadProtocol.cpp index 54ac96dd3c6fd..3f3915e006da6 100644 --- a/source/Host/common/NativeThreadProtocol.cpp +++ b/source/Host/common/NativeThreadProtocol.cpp @@ -22,43 +22,33 @@ NativeThreadProtocol::NativeThreadProtocol(NativeProcessProtocol &process, Status NativeThreadProtocol::ReadRegister(uint32_t reg, RegisterValue ®_value) { - NativeRegisterContextSP register_context_sp = GetRegisterContext(); - if (!register_context_sp) - return Status("no register context"); + NativeRegisterContext ®ister_context = GetRegisterContext(); const RegisterInfo *const reg_info = - register_context_sp->GetRegisterInfoAtIndex(reg); + register_context.GetRegisterInfoAtIndex(reg); if (!reg_info) return Status("no register info for reg num %" PRIu32, reg); - return register_context_sp->ReadRegister(reg_info, reg_value); + return register_context.ReadRegister(reg_info, reg_value); ; } Status NativeThreadProtocol::WriteRegister(uint32_t reg, const RegisterValue ®_value) { - NativeRegisterContextSP register_context_sp = GetRegisterContext(); - if (!register_context_sp) - return Status("no register context"); + NativeRegisterContext& register_context = GetRegisterContext(); const RegisterInfo *const reg_info = - register_context_sp->GetRegisterInfoAtIndex(reg); + register_context.GetRegisterInfoAtIndex(reg); if (!reg_info) return Status("no register info for reg num %" PRIu32, reg); - return register_context_sp->WriteRegister(reg_info, reg_value); + return register_context.WriteRegister(reg_info, reg_value); } Status NativeThreadProtocol::SaveAllRegisters(lldb::DataBufferSP &data_sp) { - NativeRegisterContextSP register_context_sp = GetRegisterContext(); - if (!register_context_sp) - return Status("no register context"); - return register_context_sp->WriteAllRegisterValues(data_sp); + return GetRegisterContext().WriteAllRegisterValues(data_sp); } Status NativeThreadProtocol::RestoreAllRegisters(lldb::DataBufferSP &data_sp) { - NativeRegisterContextSP register_context_sp = GetRegisterContext(); - if (!register_context_sp) - return Status("no register context"); - return register_context_sp->ReadAllRegisterValues(data_sp); + return GetRegisterContext().ReadAllRegisterValues(data_sp); } diff --git a/source/Host/common/PseudoTerminal.cpp b/source/Host/common/PseudoTerminal.cpp index 58c32e4a1c4ba..9657cb6523dce 100644 --- a/source/Host/common/PseudoTerminal.cpp +++ b/source/Host/common/PseudoTerminal.cpp @@ -24,7 +24,7 @@ int posix_openpt(int flags); #endif -using namespace lldb_utility; +using namespace lldb_private; //---------------------------------------------------------------------- // PseudoTerminal constructor diff --git a/source/Host/common/Socket.cpp b/source/Host/common/Socket.cpp index 5490e9b30bdaf..4c23e4eb560c4 100644 --- a/source/Host/common/Socket.cpp +++ b/source/Host/common/Socket.cpp @@ -450,7 +450,7 @@ NativeSocket Socket::AcceptSocket(NativeSocket sockfd, struct sockaddr *addr, close(fd); } return fd; -#elif defined(SOCK_CLOEXEC) +#elif defined(SOCK_CLOEXEC) && defined(HAVE_ACCEPT4) int flags = 0; if (!child_processes_inherit) { flags |= SOCK_CLOEXEC; diff --git a/source/Host/common/Symbols.cpp b/source/Host/common/Symbols.cpp index e7bdf084d385a..3f70fdc4bf951 100644 --- a/source/Host/common/Symbols.cpp +++ b/source/Host/common/Symbols.cpp @@ -8,11 +8,11 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/Symbols.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Log.h" @@ -109,25 +109,25 @@ static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec, // Remove the binary name from the FileSpec parent_dirs.RemoveLastPathComponent(); - // Add a ".dSYM" name to each directory component of the path, stripping - // off components. e.g. we may have a binary like + // Add a ".dSYM" name to each directory component of the path, + // stripping off components. e.g. we may have a binary like // /S/L/F/Foundation.framework/Versions/A/Foundation // and // /S/L/F/Foundation.framework.dSYM // // so we'll need to start with /S/L/F/Foundation.framework/Versions/A, // add the .dSYM part to the "A", and if that doesn't exist, strip off - // the "A" and try it again with "Versions", etc., until we find a dSYM - // bundle or we've stripped off enough path components that there's no - // need to continue. + // the "A" and try it again with "Versions", etc., until we find a + // dSYM bundle or we've stripped off enough path components that + // there's no need to continue. for (int i = 0; i < 4; i++) { - // Does this part of the path have a "." character - could it be a bundle's - // top level directory? + // Does this part of the path have a "." character - could it be a + // bundle's top level directory? const char *fn = parent_dirs.GetFilename().AsCString(); if (fn == nullptr) - break; - if (::strchr (fn, '.') != nullptr) { + break; + if (::strchr(fn, '.') != nullptr) { dsym_fspec = parent_dirs; dsym_fspec.RemoveLastPathComponent(); @@ -140,16 +140,17 @@ static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec, dsym_fspec.AppendPathComponent("Contents"); dsym_fspec.AppendPathComponent("Resources"); dsym_fspec.AppendPathComponent("DWARF"); - dsym_fspec.AppendPathComponent(exec_fspec->GetFilename().AsCString()); + dsym_fspec.AppendPathComponent( + exec_fspec->GetFilename().AsCString()); if (dsym_fspec.Exists() && - FileAtPathContainsArchAndUUID( - dsym_fspec, module_spec.GetArchitecturePtr(), - module_spec.GetUUIDPtr())) { - if (log) { - log->Printf("dSYM with matching UUID & arch found at %s", - dsym_fspec.GetPath().c_str()); - } - return true; + FileAtPathContainsArchAndUUID( + dsym_fspec, module_spec.GetArchitecturePtr(), + module_spec.GetUUIDPtr())) { + if (log) { + log->Printf("dSYM with matching UUID & arch found at %s", + dsym_fspec.GetPath().c_str()); + } + return true; } } parent_dirs.RemoveLastPathComponent(); @@ -231,7 +232,8 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) { #ifndef LLVM_ON_WIN32 #if defined(__NetBSD__) // Add /usr/libdata/debug directory. - debug_file_search_paths.AppendIfUnique(FileSpec("/usr/libdata/debug", true)); + debug_file_search_paths.AppendIfUnique( + FileSpec("/usr/libdata/debug", true)); #else // Add /usr/lib/debug directory. debug_file_search_paths.AppendIfUnique(FileSpec("/usr/lib/debug", true)); @@ -285,7 +287,11 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) { if (num_specs == 1) { ModuleSpec mspec; if (specs.GetModuleSpecAtIndex(0, mspec)) { - if (mspec.GetUUID() == module_uuid) + // Skip the uuids check if module_uuid is invalid. + // For example, this happens for *.dwp files since + // at the moment llvm-dwp doesn't output build ids, + // nor does binutils dwp. + if (!module_uuid.IsValid() || module_uuid == mspec.GetUUID()) return file_spec; } } diff --git a/source/Utility/TaskPool.cpp b/source/Host/common/TaskPool.cpp index d33f23cd861c6..156a079429985 100644 --- a/source/Utility/TaskPool.cpp +++ b/source/Host/common/TaskPool.cpp @@ -7,12 +7,15 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Utility/TaskPool.h" +#include "lldb/Host/TaskPool.h" +#include "lldb/Host/ThreadLauncher.h" #include <cstdint> // for uint32_t #include <queue> // for queue #include <thread> // for thread +namespace lldb_private { + namespace { class TaskPoolImpl { public: @@ -23,6 +26,8 @@ public: private: TaskPoolImpl(); + static lldb::thread_result_t WorkerPtr(void *pool); + static void Worker(TaskPoolImpl *pool); std::queue<std::function<void()>> m_tasks; @@ -43,21 +48,36 @@ void TaskPool::AddTaskImpl(std::function<void()> &&task_fn) { TaskPoolImpl::TaskPoolImpl() : m_thread_count(0) {} +unsigned GetHardwareConcurrencyHint() { + // std::thread::hardware_concurrency may return 0 + // if the value is not well defined or not computable. + static const unsigned g_hardware_concurrency = + std::max(1u, std::thread::hardware_concurrency()); + return g_hardware_concurrency; +} + void TaskPoolImpl::AddTask(std::function<void()> &&task_fn) { - static const uint32_t max_threads = std::thread::hardware_concurrency(); + const size_t min_stack_size = 8 * 1024 * 1024; std::unique_lock<std::mutex> lock(m_tasks_mutex); m_tasks.emplace(std::move(task_fn)); - if (m_thread_count < max_threads) { + if (m_thread_count < GetHardwareConcurrencyHint()) { m_thread_count++; // Note that this detach call needs to happen with the m_tasks_mutex held. // This prevents the thread // from exiting prematurely and triggering a linux libc bug // (https://sourceware.org/bugzilla/show_bug.cgi?id=19951). - std::thread(Worker, this).detach(); + lldb_private::ThreadLauncher::LaunchThread("task-pool.worker", WorkerPtr, + this, nullptr, min_stack_size) + .Release(); } } +lldb::thread_result_t TaskPoolImpl::WorkerPtr(void *pool) { + Worker((TaskPoolImpl *)pool); + return 0; +} + void TaskPoolImpl::Worker(TaskPoolImpl *pool) { while (true) { std::unique_lock<std::mutex> lock(pool->m_tasks_mutex); @@ -66,7 +86,7 @@ void TaskPoolImpl::Worker(TaskPoolImpl *pool) { break; } - std::function<void()> f = pool->m_tasks.front(); + std::function<void()> f = std::move(pool->m_tasks.front()); pool->m_tasks.pop(); lock.unlock(); @@ -76,10 +96,9 @@ void TaskPoolImpl::Worker(TaskPoolImpl *pool) { void TaskMapOverInt(size_t begin, size_t end, const llvm::function_ref<void(size_t)> &func) { + const size_t num_workers = std::min<size_t>(end, GetHardwareConcurrencyHint()); std::atomic<size_t> idx{begin}; - size_t num_workers = - std::min<size_t>(end, std::thread::hardware_concurrency()); - + auto wrapper = [&idx, end, &func]() { while (true) { size_t i = idx.fetch_add(1); @@ -96,3 +115,6 @@ void TaskMapOverInt(size_t begin, size_t end, for (size_t i = 0; i < num_workers; i++) futures[i].wait(); } + +} // namespace lldb_private + diff --git a/source/Host/common/XML.cpp b/source/Host/common/XML.cpp index c637d938dffa6..c3169bd6e08d1 100644 --- a/source/Host/common/XML.cpp +++ b/source/Host/common/XML.cpp @@ -339,7 +339,7 @@ XMLNode XMLNode::FindFirstChildElementWithName(const char *name) const { #if defined(LIBXML2_DEFINED) ForEachChildElementWithName( - name, [&result_node, name](const XMLNode &node) -> bool { + name, [&result_node](const XMLNode &node) -> bool { result_node = node; // Stop iterating, we found the node we wanted return false; diff --git a/source/Host/freebsd/Host.cpp b/source/Host/freebsd/Host.cpp index 037dfc7f5e033..124a8a760133a 100644 --- a/source/Host/freebsd/Host.cpp +++ b/source/Host/freebsd/Host.cpp @@ -73,7 +73,14 @@ GetFreeBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, if (!cstr) return false; - process_info.GetExecutableFile().SetFile(cstr, false); + // Get pathname for pid. If that fails fall back to argv[0]. + char pathname[MAXPATHLEN]; + size_t pathname_len = sizeof(pathname); + mib[2] = KERN_PROC_PATHNAME; + if (::sysctl(mib, 4, pathname, &pathname_len, NULL, 0) == 0) + process_info.GetExecutableFile().SetFile(pathname, false); + else + process_info.GetExecutableFile().SetFile(cstr, false); if (!(match_info_ptr == NULL || NameMatches(process_info.GetExecutableFile().GetFilename().GetCString(), diff --git a/source/Host/macosx/Host.mm b/source/Host/macosx/Host.mm index 75624ef21f432..7359815fdf704 100644 --- a/source/Host/macosx/Host.mm +++ b/source/Host/macosx/Host.mm @@ -20,7 +20,7 @@ #define __XPC_PRIVATE_H__ #include <xpc/xpc.h> -#define LaunchUsingXPCRightName "com.apple.dt.Xcode.RootDebuggingXPCService" +#define LaunchUsingXPCRightName "com.apple.lldb.RootDebuggingXPCService" // These XPC messaging keys are used for communication between Host.mm and the // XPC service. @@ -54,7 +54,6 @@ #include <sys/types.h> #include <unistd.h> -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Communication.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" @@ -63,6 +62,7 @@ #include "lldb/Host/ThreadLauncher.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/CleanUp.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataExtractor.h" diff --git a/source/Host/macosx/Symbols.cpp b/source/Host/macosx/Symbols.cpp index 9d1e8fe96ae98..98c110b1bed67 100644 --- a/source/Host/macosx/Symbols.cpp +++ b/source/Host/macosx/Symbols.cpp @@ -23,11 +23,11 @@ #include "Host/macosx/cfcpp/CFCData.h" #include "Host/macosx/cfcpp/CFCReleaser.h" #include "Host/macosx/cfcpp/CFCString.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Host/Host.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/CleanUp.h" #include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/DataExtractor.h" @@ -361,6 +361,7 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, // If we see DBGVersion with a value of 2 or higher, this is a new style // DBGSourcePathRemapping dictionary bool new_style_source_remapping_dictionary = false; + bool do_truncate_remapping_names = false; std::string original_DBGSourcePath_value = DBGSourcePath; cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict, CFSTR("DBGVersion")); @@ -372,6 +373,9 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, if (version_number > 1) { new_style_source_remapping_dictionary = true; } + if (version_number == 2) { + do_truncate_remapping_names = true; + } } } @@ -409,9 +413,24 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, FileSpec resolved_source_path(DBGSourcePath.c_str(), true); DBGSourcePath = resolved_source_path.GetPath(); } + // With version 2 of DBGSourcePathRemapping, we can chop off the + // last two filename parts from the source remapping and get a + // more general source remapping that still works. Add this as + // another option in addition to the full source path remap. module_spec.GetSourceMappingList().Append( ConstString(DBGBuildSourcePath.c_str()), ConstString(DBGSourcePath.c_str()), true); + if (do_truncate_remapping_names) { + FileSpec build_path(DBGBuildSourcePath.c_str(), false); + FileSpec source_path(DBGSourcePath.c_str(), false); + build_path.RemoveLastPathComponent(); + build_path.RemoveLastPathComponent(); + source_path.RemoveLastPathComponent(); + source_path.RemoveLastPathComponent(); + module_spec.GetSourceMappingList().Append( + ConstString(build_path.GetPath().c_str()), + ConstString(source_path.GetPath().c_str()), true); + } } } if (keys) diff --git a/source/Host/posix/HostThreadPosix.cpp b/source/Host/posix/HostThreadPosix.cpp index 0f4434d25e2eb..71abb76dc600b 100644 --- a/source/Host/posix/HostThreadPosix.cpp +++ b/source/Host/posix/HostThreadPosix.cpp @@ -43,7 +43,7 @@ Status HostThreadPosix::Cancel() { if (IsJoinable()) { #ifndef __ANDROID__ #ifndef __FreeBSD__ - assert(false && "someone is calling HostThread::Cancel()"); + llvm_unreachable("someone is calling HostThread::Cancel()"); #endif int err = ::pthread_cancel(m_thread); error.SetError(err, eErrorTypePOSIX); diff --git a/source/Host/posix/ProcessLauncherPosixFork.cpp b/source/Host/posix/ProcessLauncherPosixFork.cpp index 66c0229e0dab4..ac1d9011c2b78 100644 --- a/source/Host/posix/ProcessLauncherPosixFork.cpp +++ b/source/Host/posix/ProcessLauncherPosixFork.cpp @@ -29,7 +29,7 @@ #define PT_TRACE_ME PTRACE_TRACEME #endif -#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 +#if defined(__ANDROID_API__) && __ANDROID_API__ < 15 #include <linux/personality.h> #elif defined(__linux__) #include <sys/personality.h> @@ -95,10 +95,6 @@ static void DupDescriptor(int error_fd, const FileSpec &file_spec, int fd, static void LLVM_ATTRIBUTE_NORETURN ChildFunc(int error_fd, const ProcessLaunchInfo &info) { - // First, make sure we disable all logging. If we are logging to stdout, our - // logs can be mistaken for inferior output. - Log::DisableAllLogChannels(); - // Do not inherit setgid powers. if (setgid(getgid()) != 0) ExitWithError(error_fd, "setgid"); diff --git a/source/Initialization/SystemInitializerCommon.cpp b/source/Initialization/SystemInitializerCommon.cpp index e76ba4122bb6f..a8fc46c119d8b 100644 --- a/source/Initialization/SystemInitializerCommon.cpp +++ b/source/Initialization/SystemInitializerCommon.cpp @@ -69,8 +69,10 @@ void SystemInitializerCommon::Initialize() { } #endif +#if not defined(__APPLE__) llvm::EnablePrettyStackTrace(); - InitializeLog(); +#endif + Log::Initialize(); HostInfo::Initialize(); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); diff --git a/source/Interpreter/Args.cpp b/source/Interpreter/Args.cpp index a23ba3094b22b..07e5191f898aa 100644 --- a/source/Interpreter/Args.cpp +++ b/source/Interpreter/Args.cpp @@ -185,6 +185,11 @@ Args::Args(llvm::StringRef command) { SetCommandString(command); } Args::Args(const Args &rhs) { *this = rhs; } +Args::Args(const StringList &list) : Args() { + for(size_t i = 0; i < list.GetSize(); ++i) + AppendArgument(list[i]); +} + Args &Args::operator=(const Args &rhs) { Clear(); diff --git a/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp index 986be7ffbf89c..8dc5637b6e4eb 100644 --- a/source/Interpreter/CommandInterpreter.cpp +++ b/source/Interpreter/CommandInterpreter.cpp @@ -546,7 +546,7 @@ void CommandInterpreter::LoadCommandDictionary() { char buffer[1024]; int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o"); - assert(num_printed < 1024); + lldbassert(num_printed < 1024); UNUSED_IF_ASSERT_DISABLED(num_printed); success = tbreak_regex_cmd_ap->AddRegexCommand(break_regexes[i][0], buffer); @@ -891,8 +891,8 @@ bool CommandInterpreter::AddCommand(llvm::StringRef name, const lldb::CommandObjectSP &cmd_sp, bool can_replace) { if (cmd_sp.get()) - assert((this == &cmd_sp->GetCommandInterpreter()) && - "tried to add a CommandObject from a different interpreter"); + lldbassert((this == &cmd_sp->GetCommandInterpreter()) && + "tried to add a CommandObject from a different interpreter"); if (name.empty()) return false; @@ -913,8 +913,8 @@ bool CommandInterpreter::AddUserCommand(llvm::StringRef name, const lldb::CommandObjectSP &cmd_sp, bool can_replace) { if (cmd_sp.get()) - assert((this == &cmd_sp->GetCommandInterpreter()) && - "tried to add a CommandObject from a different interpreter"); + lldbassert((this == &cmd_sp->GetCommandInterpreter()) && + "tried to add a CommandObject from a different interpreter"); if (!name.empty()) { // do not allow replacement of internal commands @@ -1062,8 +1062,8 @@ CommandInterpreter::AddAlias(llvm::StringRef alias_name, lldb::CommandObjectSP &command_obj_sp, llvm::StringRef args_string) { if (command_obj_sp.get()) - assert((this == &command_obj_sp->GetCommandInterpreter()) && - "tried to add a CommandObject from a different interpreter"); + lldbassert((this == &command_obj_sp->GetCommandInterpreter()) && + "tried to add a CommandObject from a different interpreter"); std::unique_ptr<CommandAlias> command_alias_up( new CommandAlias(*this, command_obj_sp, args_string, alias_name)); @@ -1541,6 +1541,12 @@ bool CommandInterpreter::HandleCommand(const char *command_line, if (!no_context_switching) UpdateExecutionContext(override_context); + if (WasInterrupted()) { + result.AppendError("interrupted"); + result.SetStatus(eReturnStatusFailed); + return false; + } + bool add_to_history; if (lazy_add_to_history == eLazyBoolCalculate) add_to_history = (m_command_source_depth == 0); @@ -1839,7 +1845,7 @@ int CommandInterpreter::HandleCompletion( matches.Clear(); // Only max_return_elements == -1 is supported at present: - assert(max_return_elements == -1); + lldbassert(max_return_elements == -1); bool word_complete; num_command_matches = HandleCompletionMatches( parsed_line, cursor_index, cursor_char_position, match_start_point, @@ -2210,7 +2216,7 @@ void CommandInterpreter::HandleCommands(const StringList &commands, m_debugger.SetAsyncExecution(false); } - for (size_t idx = 0; idx < num_lines; idx++) { + for (size_t idx = 0; idx < num_lines && !WasInterrupted(); idx++) { const char *cmd = commands.GetStringAtIndex(idx); if (cmd[0] == '\0') continue; @@ -2569,7 +2575,7 @@ void CommandInterpreter::OutputHelpText(Stream &strm, llvm::StringRef word_text, while (!text.empty()) { if (text.front() == '\n' || - (text.front() == ' ' && nextWordLength(text.ltrim(' ')) < chars_left)) { + (text.front() == ' ' && nextWordLength(text.ltrim(' ')) > chars_left)) { strm.EOL(); strm.Indent(); chars_left = max_columns - indent_size; @@ -2677,8 +2683,67 @@ size_t CommandInterpreter::GetProcessOutput() { return total_bytes; } +void CommandInterpreter::StartHandlingCommand() { + auto idle_state = CommandHandlingState::eIdle; + if (m_command_state.compare_exchange_strong( + idle_state, CommandHandlingState::eInProgress)) + lldbassert(m_iohandler_nesting_level == 0); + else + lldbassert(m_iohandler_nesting_level > 0); + ++m_iohandler_nesting_level; +} + +void CommandInterpreter::FinishHandlingCommand() { + lldbassert(m_iohandler_nesting_level > 0); + if (--m_iohandler_nesting_level == 0) { + auto prev_state = m_command_state.exchange(CommandHandlingState::eIdle); + lldbassert(prev_state != CommandHandlingState::eIdle); + } +} + +bool CommandInterpreter::InterruptCommand() { + auto in_progress = CommandHandlingState::eInProgress; + return m_command_state.compare_exchange_strong( + in_progress, CommandHandlingState::eInterrupted); +} + +bool CommandInterpreter::WasInterrupted() const { + bool was_interrupted = + (m_command_state == CommandHandlingState::eInterrupted); + lldbassert(!was_interrupted || m_iohandler_nesting_level > 0); + return was_interrupted; +} + +void CommandInterpreter::PrintCommandOutput(Stream &stream, + llvm::StringRef str) { + // Split the output into lines and poll for interrupt requests + const char *data = str.data(); + size_t size = str.size(); + while (size > 0 && !WasInterrupted()) { + size_t chunk_size = 0; + for (; chunk_size < size; ++chunk_size) { + lldbassert(data[chunk_size] != '\0'); + if (data[chunk_size] == '\n') { + ++chunk_size; + break; + } + } + chunk_size = stream.Write(data, chunk_size); + lldbassert(size >= chunk_size); + data += chunk_size; + size -= chunk_size; + } + if (size > 0) { + stream.Printf("\n... Interrupted.\n"); + } +} + void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler, std::string &line) { + // If we were interrupted, bail out... + if (WasInterrupted()) + return; + const bool is_interactive = io_handler.GetIsInteractive(); if (is_interactive == false) { // When we are not interactive, don't execute blank lines. This will happen @@ -2700,6 +2765,8 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler, line.c_str()); } + StartHandlingCommand(); + lldb_private::CommandReturnObject result; HandleCommand(line.c_str(), eLazyBoolCalculate, result); @@ -2710,18 +2777,18 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler, if (!result.GetImmediateOutputStream()) { llvm::StringRef output = result.GetOutputData(); - if (!output.empty()) - io_handler.GetOutputStreamFile()->PutCString(output); + PrintCommandOutput(*io_handler.GetOutputStreamFile(), output); } // Now emit the command error text from the command we just executed if (!result.GetImmediateErrorStream()) { llvm::StringRef error = result.GetErrorData(); - if (!error.empty()) - io_handler.GetErrorStreamFile()->PutCString(error); + PrintCommandOutput(*io_handler.GetErrorStreamFile(), error); } } + FinishHandlingCommand(); + switch (result.GetStatus()) { case eReturnStatusInvalid: case eReturnStatusSuccessFinishNoResult: @@ -2777,6 +2844,9 @@ bool CommandInterpreter::IOHandlerInterrupt(IOHandler &io_handler) { ExecutionContext exe_ctx(GetExecutionContext()); Process *process = exe_ctx.GetProcessPtr(); + if (InterruptCommand()) + return true; + if (process) { StateType state = process->GetState(); if (StateIsRunningState(state)) { @@ -2998,7 +3068,7 @@ CommandInterpreter::ResolveCommandImpl(std::string &command_line, result.AppendRawError(error_msg.GetString()); } else { // We didn't have only one match, otherwise we wouldn't get here. - assert(num_matches == 0); + lldbassert(num_matches == 0); result.AppendErrorWithFormat("'%s' is not a valid command.\n", next_word.c_str()); } diff --git a/source/Interpreter/CommandObject.cpp b/source/Interpreter/CommandObject.cpp index f9a5b10bb4b8f..98a6a941864e7 100644 --- a/source/Interpreter/CommandObject.cpp +++ b/source/Interpreter/CommandObject.cpp @@ -17,8 +17,8 @@ #include <stdlib.h> #include "lldb/Core/Address.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Interpreter/Options.h" +#include "lldb/Utility/ArchSpec.h" // These are for the Sourcename completers. // FIXME: Make a separate file for the completers. @@ -57,7 +57,7 @@ llvm::StringRef CommandObject::GetHelp() { return m_cmd_help_short; } llvm::StringRef CommandObject::GetHelpLong() { return m_cmd_help_long; } llvm::StringRef CommandObject::GetSyntax() { - if (m_cmd_syntax.empty()) + if (!m_cmd_syntax.empty()) return m_cmd_syntax; StreamString syntax_str; @@ -1113,7 +1113,8 @@ CommandObject::ArgumentTableEntry CommandObject::g_arguments_data[] = { { eArgTypeWatchpointID, "watchpt-id", CommandCompletions::eNoCompletion, { nullptr, false }, "Watchpoint IDs are positive integers." }, { eArgTypeWatchpointIDRange, "watchpt-id-list", CommandCompletions::eNoCompletion, { nullptr, false }, "For example, '1-3' or '1 to 3'." }, { eArgTypeWatchType, "watch-type", CommandCompletions::eNoCompletion, { nullptr, false }, "Specify the type for a watchpoint." }, - { eArgRawInput, "raw-input", CommandCompletions::eNoCompletion, { nullptr, false }, "Free-form text passed to a command without prior interpretation, allowing spaces without requiring quotes. To pass arguments and free form text put two dashes ' -- ' between the last argument and any raw input." } + { eArgRawInput, "raw-input", CommandCompletions::eNoCompletion, { nullptr, false }, "Free-form text passed to a command without prior interpretation, allowing spaces without requiring quotes. To pass arguments and free form text put two dashes ' -- ' between the last argument and any raw input." }, + { eArgTypeCommand, "command", CommandCompletions::eNoCompletion, { nullptr, false }, "An LLDB Command line command." } // clang-format on }; diff --git a/source/Interpreter/OptionGroupArchitecture.cpp b/source/Interpreter/OptionGroupArchitecture.cpp index d5354fe0739cb..bbd69b8f13fce 100644 --- a/source/Interpreter/OptionGroupArchitecture.cpp +++ b/source/Interpreter/OptionGroupArchitecture.cpp @@ -8,12 +8,8 @@ //===----------------------------------------------------------------------===// #include "lldb/Interpreter/OptionGroupArchitecture.h" - -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes #include "lldb/Host/OptionParser.h" +#include "lldb/Target/Platform.h" using namespace lldb; using namespace lldb_private; @@ -34,10 +30,7 @@ llvm::ArrayRef<OptionDefinition> OptionGroupArchitecture::GetDefinitions() { bool OptionGroupArchitecture::GetArchitecture(Platform *platform, ArchSpec &arch) { - if (m_arch_str.empty()) - arch.Clear(); - else - arch.SetTriple(m_arch_str.c_str(), platform); + arch = Platform::GetAugmentedArchSpec(platform, m_arch_str); return arch.IsValid(); } diff --git a/source/Interpreter/OptionGroupFormat.cpp b/source/Interpreter/OptionGroupFormat.cpp index 7c4239f92642e..75d8df950f183 100644 --- a/source/Interpreter/OptionGroupFormat.cpp +++ b/source/Interpreter/OptionGroupFormat.cpp @@ -9,11 +9,6 @@ #include "lldb/Interpreter/OptionGroupFormat.h" -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Target/ExecutionContext.h" diff --git a/source/Interpreter/OptionValueDictionary.cpp b/source/Interpreter/OptionValueDictionary.cpp index b245a09c19514..a57ede4863193 100644 --- a/source/Interpreter/OptionValueDictionary.cpp +++ b/source/Interpreter/OptionValueDictionary.cpp @@ -227,8 +227,7 @@ OptionValueDictionary::GetSubValue(const ExecutionContext *exe_ctx, } assert(!temp.empty()); - llvm::StringRef key, value; - llvm::StringRef quote_char; + llvm::StringRef key, quote_char; if (temp[0] == '\"' || temp[0] == '\'') { quote_char = temp.take_front(); diff --git a/source/Interpreter/ScriptInterpreter.cpp b/source/Interpreter/ScriptInterpreter.cpp index 57f7eea6e4c1c..497ad283f1a4a 100644 --- a/source/Interpreter/ScriptInterpreter.cpp +++ b/source/Interpreter/ScriptInterpreter.cpp @@ -69,10 +69,9 @@ lldb::ScriptLanguage ScriptInterpreter::StringToLanguage(const llvm::StringRef &language) { if (language.equals_lower(LanguageToString(eScriptLanguageNone))) return eScriptLanguageNone; - else if (language.equals_lower(LanguageToString(eScriptLanguagePython))) + if (language.equals_lower(LanguageToString(eScriptLanguagePython))) return eScriptLanguagePython; - else - return eScriptLanguageUnknown; + return eScriptLanguageUnknown; } Status ScriptInterpreter::SetBreakpointCommandCallback( diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp index fd5ee6ede4c37..1bd1c1bf8dd40 100644 --- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp +++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp @@ -1413,10 +1413,6 @@ bool ABIMacOSX_arm::PrepareTrivialCall(Thread &thread, addr_t sp, if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_num, return_addr)) return false; - // Set "sp" to the requested value - if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp)) - return false; - // If bit zero or 1 is set, this must be a thumb function, no need to figure // this out from the symbols. so_addr.SetLoadAddress(function_addr, target_sp.get()); @@ -1441,6 +1437,11 @@ bool ABIMacOSX_arm::PrepareTrivialCall(Thread &thread, addr_t sp, function_addr &= ~1ull; // clear bit zero since the CPSR will take care of the mode for us + // Update the sp - stack pointer - to be aligned to 16-bytes + sp &= ~(0xfull); + if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp)) + return false; + // Set "pc" to the address requested if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, function_addr)) return false; diff --git a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp index f91ed851a3e54..dbe333c4649e5 100644 --- a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp +++ b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp @@ -2018,7 +2018,7 @@ bool ABISysV_arm64::RegisterIsVolatile(const RegisterInfo *reg_info) { if (name[0] == 'l' && name[1] == 'r') // lr return false; - if (name[0] == 'x') { + if (name[0] == 'x' || name[0] == 'r') { // Volatile registers: x0-x18 // Although documentation says only x19-28 + sp are callee saved // We ll also have to treat x30 as non-volatile. diff --git a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp index 63da5a77b48fb..d799c587dd077 100644 --- a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp +++ b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp @@ -205,11 +205,12 @@ ABISysV_i386::GetRegisterInfoArray(uint32_t &count) { ABISP ABISysV_i386::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { static ABISP g_abi_sp; - if ((arch.GetTriple().getArch() == llvm::Triple::x86) && - arch.GetTriple().isOSLinux()) { - if (!g_abi_sp) - g_abi_sp.reset(new ABISysV_i386(process_sp)); - return g_abi_sp; + if (arch.GetTriple().getVendor() != llvm::Triple::Apple) { + if (arch.GetTriple().getArch() == llvm::Triple::x86) { + if (!g_abi_sp) + g_abi_sp.reset(new ABISysV_i386(process_sp)); + return g_abi_sp; + } } return ABISP(); } diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp index 06a8ce932fdae..2fee176739f3f 100644 --- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp +++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp @@ -291,47 +291,6 @@ bool ABISysV_ppc::PrepareTrivialCall(Thread &thread, addr_t sp, RegisterValue reg_value; -#if 0 - // This code adds an extra frame so that we don't lose the function that we came from - // by pushing the PC and the FP and then writing the current FP to point to the FP value - // we just pushed. It is disabled for now until the stack backtracing code can be debugged. - - // Save current PC - const RegisterInfo *fp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); - if (reg_ctx->ReadRegister(pc_reg_info, reg_value)) - { - if (log) - log->Printf("Pushing the current PC onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64()); - - if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error)) - return false; - - sp -= 8; - - // Save current FP - if (reg_ctx->ReadRegister(fp_reg_info, reg_value)) - { - if (log) - log->Printf("Pushing the current FP onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64()); - - if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error)) - return false; - } - // Setup FP backchain - reg_value.SetUInt64 (sp); - - if (log) - log->Printf("Writing FP: 0x%" PRIx64 " (for FP backchain)", reg_value.GetAsUInt64()); - - if (!reg_ctx->WriteRegister(fp_reg_info, reg_value)) - { - return false; - } - - sp -= 8; - } -#endif - if (log) log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp index c090f01ccb1cd..0348853c7fa06 100644 --- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp +++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp @@ -291,47 +291,6 @@ bool ABISysV_ppc64::PrepareTrivialCall(Thread &thread, addr_t sp, RegisterValue reg_value; -#if 0 - // This code adds an extra frame so that we don't lose the function that we came from - // by pushing the PC and the FP and then writing the current FP to point to the FP value - // we just pushed. It is disabled for now until the stack backtracing code can be debugged. - - // Save current PC - const RegisterInfo *fp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); - if (reg_ctx->ReadRegister(pc_reg_info, reg_value)) - { - if (log) - log->Printf("Pushing the current PC onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64()); - - if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error)) - return false; - - sp -= 8; - - // Save current FP - if (reg_ctx->ReadRegister(fp_reg_info, reg_value)) - { - if (log) - log->Printf("Pushing the current FP onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64()); - - if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error)) - return false; - } - // Setup FP backchain - reg_value.SetUInt64 (sp); - - if (log) - log->Printf("Writing FP: 0x%" PRIx64 " (for FP backchain)", reg_value.GetAsUInt64()); - - if (!reg_ctx->WriteRegister(fp_reg_info, reg_value)) - { - return false; - } - - sp -= 8; - } -#endif - if (log) log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, 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 10bbae5664918..41d146f245269 100644 --- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp +++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp @@ -13,6 +13,7 @@ // C++ Includes // Other libraries and framework includes #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" // Project includes @@ -1160,48 +1161,6 @@ bool ABISysV_x86_64::PrepareTrivialCall(Thread &thread, addr_t sp, ProcessSP process_sp(thread.GetProcess()); RegisterValue reg_value; - -#if 0 - // This code adds an extra frame so that we don't lose the function that we came from - // by pushing the PC and the FP and then writing the current FP to point to the FP value - // we just pushed. It is disabled for now until the stack backtracing code can be debugged. - - // Save current PC - const RegisterInfo *fp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); - if (reg_ctx->ReadRegister(pc_reg_info, reg_value)) - { - if (log) - log->Printf("Pushing the current PC onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64()); - - if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error)) - return false; - - sp -= 8; - - // Save current FP - if (reg_ctx->ReadRegister(fp_reg_info, reg_value)) - { - if (log) - log->Printf("Pushing the current FP onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64()); - - if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error)) - return false; - } - // Setup FP backchain - reg_value.SetUInt64 (sp); - - if (log) - log->Printf("Writing FP: 0x%" PRIx64 " (for FP backchain)", reg_value.GetAsUInt64()); - - if (!reg_ctx->WriteRegister(fp_reg_info, reg_value)) - { - return false; - } - - sp -= 8; - } -#endif - if (log) log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, @@ -1908,52 +1867,16 @@ bool ABISysV_x86_64::RegisterIsVolatile(const RegisterInfo *reg_info) { // It's being revised & updated at https://github.com/hjl-tools/x86-psABI/ bool ABISysV_x86_64::RegisterIsCalleeSaved(const RegisterInfo *reg_info) { - if (reg_info) { - // Preserved registers are : - // rbx, rsp, rbp, r12, r13, r14, r15 - // mxcsr (partially preserved) - // x87 control word - - const char *name = reg_info->name; - if (name[0] == 'r') { - switch (name[1]) { - case '1': // r12, r13, r14, r15 - if (name[2] >= '2' && name[2] <= '5') - return name[3] == '\0'; - break; - - default: - break; - } - } - - // Accept shorter-variant versions, rbx/ebx, rip/ eip, etc. - if (name[0] == 'r' || name[0] == 'e') { - switch (name[1]) { - case 'b': // rbp, rbx - if (name[2] == 'p' || name[2] == 'x') - return name[3] == '\0'; - break; - - case 'i': // rip - if (name[2] == 'p') - return name[3] == '\0'; - break; - - case 's': // rsp - if (name[2] == 'p') - return name[3] == '\0'; - break; - } - } - if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp - return true; - if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp - return true; - if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc - return true; - } - return false; + if (!reg_info) + return false; + assert(reg_info->name != nullptr && "unnamed register?"); + std::string Name = std::string(reg_info->name); + bool IsCalleeSaved = + llvm::StringSwitch<bool>(Name) + .Cases("r12", "r13", "r14", "r15", "rbp", "ebp", "rbx", "ebx", true) + .Cases("rip", "eip", "rsp", "esp", "sp", "fp", "pc", true) + .Default(false); + return IsCalleeSaved; } void ABISysV_x86_64::Initialize() { diff --git a/source/Plugins/Architecture/Arm/ArchitectureArm.cpp b/source/Plugins/Architecture/Arm/ArchitectureArm.cpp new file mode 100644 index 0000000000000..abac6d3001af1 --- /dev/null +++ b/source/Plugins/Architecture/Arm/ArchitectureArm.cpp @@ -0,0 +1,131 @@ +//===-- ArchitectureArm.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Plugins/Architecture/Arm/ArchitectureArm.h" +#include "Plugins/Process/Utility/ARMDefines.h" +#include "Plugins/Process/Utility/InstructionUtils.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/ArchSpec.h" + +using namespace lldb_private; +using namespace lldb; + +ConstString ArchitectureArm::GetPluginNameStatic() { + return ConstString("arm"); +} + +void ArchitectureArm::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + "Arm-specific algorithms", + &ArchitectureArm::Create); +} + +void ArchitectureArm::Terminate() { + PluginManager::UnregisterPlugin(&ArchitectureArm::Create); +} + +std::unique_ptr<Architecture> ArchitectureArm::Create(const ArchSpec &arch) { + if (arch.GetMachine() != llvm::Triple::arm) + return nullptr; + return std::unique_ptr<Architecture>(new ArchitectureArm()); +} + +ConstString ArchitectureArm::GetPluginName() { return GetPluginNameStatic(); } +uint32_t ArchitectureArm::GetPluginVersion() { return 1; } + +void ArchitectureArm::OverrideStopInfo(Thread &thread) { + // We need to check if we are stopped in Thumb mode in a IT instruction + // and detect if the condition doesn't pass. If this is the case it means + // we won't actually execute this instruction. If this happens we need to + // clear the stop reason to no thread plans think we are stopped for a + // reason and the plans should keep going. + // + // We do this because when single stepping many ARM processes, debuggers + // often use the BVR/BCR registers that says "stop when the PC is not + // equal to its current value". This method of stepping means we can end + // up stopping on instructions inside an if/then block that wouldn't get + // executed. By fixing this we can stop the debugger from seeming like + // you stepped through both the "if" _and_ the "else" clause when source + // level stepping because the debugger stops regardless due to the BVR/BCR + // triggering a stop. + // + // It also means we can set breakpoints on instructions inside an an + // if/then block and correctly skip them if we use the BKPT instruction. + // The ARM and Thumb BKPT instructions are unconditional even when executed + // in a Thumb IT block. + // + // If your debugger inserts software traps in ARM/Thumb code, it will + // need to use 16 and 32 bit instruction for 16 and 32 bit thumb + // instructions respectively. If your debugger inserts a 16 bit thumb + // trap on top of a 32 bit thumb instruction for an opcode that is inside + // an if/then, it will change the it/then to conditionally execute your + // 16 bit trap and then cause your program to crash if it executes the + // trailing 16 bits (the second half of the 32 bit thumb instruction you + // partially overwrote). + + RegisterContextSP reg_ctx_sp(thread.GetRegisterContext()); + if (!reg_ctx_sp) + return; + + const uint32_t cpsr = reg_ctx_sp->GetFlags(0); + if (cpsr == 0) + return; + + // Read the J and T bits to get the ISETSTATE + const uint32_t J = Bit32(cpsr, 24); + const uint32_t T = Bit32(cpsr, 5); + const uint32_t ISETSTATE = J << 1 | T; + if (ISETSTATE == 0) { +// NOTE: I am pretty sure we want to enable the code below +// that detects when we stop on an instruction in ARM mode +// that is conditional and the condition doesn't pass. This +// can happen if you set a breakpoint on an instruction that +// is conditional. We currently will _always_ stop on the +// instruction which is bad. You can also run into this while +// single stepping and you could appear to run code in the "if" +// and in the "else" clause because it would stop at all of the +// conditional instructions in both. +// In such cases, we really don't want to stop at this location. +// I will check with the lldb-dev list first before I enable this. +#if 0 + // ARM mode: check for condition on intsruction + const addr_t pc = reg_ctx_sp->GetPC(); + Status error; + // If we fail to read the opcode we will get UINT64_MAX as the + // result in "opcode" which we can use to detect if we read a + // valid opcode. + const uint64_t opcode = thread.GetProcess()->ReadUnsignedIntegerFromMemory(pc, 4, UINT64_MAX, error); + if (opcode <= UINT32_MAX) + { + const uint32_t condition = Bits32((uint32_t)opcode, 31, 28); + if (!ARMConditionPassed(condition, cpsr)) + { + // We ARE stopped on an ARM instruction whose condition doesn't + // pass so this instruction won't get executed. + // Regardless of why it stopped, we need to clear the stop info + thread.SetStopInfo (StopInfoSP()); + } + } +#endif + } else if (ISETSTATE == 1) { + // Thumb mode + const uint32_t ITSTATE = Bits32(cpsr, 15, 10) << 2 | Bits32(cpsr, 26, 25); + if (ITSTATE != 0) { + const uint32_t condition = Bits32(ITSTATE, 7, 4); + if (!ARMConditionPassed(condition, cpsr)) { + // We ARE stopped in a Thumb IT instruction on an instruction whose + // condition doesn't pass so this instruction won't get executed. + // Regardless of why it stopped, we need to clear the stop info + thread.SetStopInfo(StopInfoSP()); + } + } + } +} diff --git a/source/Plugins/Architecture/Arm/ArchitectureArm.h b/source/Plugins/Architecture/Arm/ArchitectureArm.h new file mode 100644 index 0000000000000..9ce6c69ef271f --- /dev/null +++ b/source/Plugins/Architecture/Arm/ArchitectureArm.h @@ -0,0 +1,35 @@ +//===-- ArchitectureArm.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PLUGIN_ARCHITECTURE_ARM_H +#define LLDB_PLUGIN_ARCHITECTURE_ARM_H + +#include "lldb/Core/Architecture.h" + +namespace lldb_private { + +class ArchitectureArm : public Architecture { +public: + static ConstString GetPluginNameStatic(); + static void Initialize(); + static void Terminate(); + + ConstString GetPluginName() override; + uint32_t GetPluginVersion() override; + + void OverrideStopInfo(Thread &thread) override; + +private: + static std::unique_ptr<Architecture> Create(const ArchSpec &arch); + ArchitectureArm() = default; +}; + +} // namespace lldb_private + +#endif // LLDB_PLUGIN_ARCHITECTURE_ARM_H diff --git a/source/Plugins/Architecture/Arm/CMakeLists.txt b/source/Plugins/Architecture/Arm/CMakeLists.txt new file mode 100644 index 0000000000000..60bbe69a99fbf --- /dev/null +++ b/source/Plugins/Architecture/Arm/CMakeLists.txt @@ -0,0 +1,11 @@ +add_lldb_library(lldbPluginArchitectureArm PLUGIN + ArchitectureArm.cpp + + LINK_LIBS + lldbPluginProcessUtility + lldbCore + lldbTarget + lldbUtility + LINK_COMPONENTS + Support + ) diff --git a/source/Plugins/Architecture/CMakeLists.txt b/source/Plugins/Architecture/CMakeLists.txt new file mode 100644 index 0000000000000..5abaa8e682310 --- /dev/null +++ b/source/Plugins/Architecture/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(Arm) diff --git a/source/Plugins/CMakeLists.txt b/source/Plugins/CMakeLists.txt index ac1afcbc331ea..5092b210a12cf 100644 --- a/source/Plugins/CMakeLists.txt +++ b/source/Plugins/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(ABI) +add_subdirectory(Architecture) add_subdirectory(Disassembler) add_subdirectory(DynamicLoader) add_subdirectory(ExpressionParser) diff --git a/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp index a82b3fe267b3f..a81a0306671e1 100644 --- a/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp +++ b/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp @@ -1229,6 +1229,16 @@ bool DynamicLoaderDarwinKernel::ParseKextSummaries( break; } } + // If this "kext" entry is actually an alias for the kernel -- + // the kext was compiled into the kernel or something -- then + // we don't want to load the kernel's text section at a different + // address. Ignore this kext entry. + if (kext_summaries[new_kext].GetUUID().IsValid() + && m_kernel.GetUUID().IsValid() + && kext_summaries[new_kext].GetUUID() == m_kernel.GetUUID()) { + to_be_added[new_kext] = false; + break; + } if (add_this_one) { number_of_new_kexts_being_added++; } @@ -1397,7 +1407,7 @@ bool DynamicLoaderDarwinKernel::ReadAllKextSummaries() { void DynamicLoaderDarwinKernel::KextImageInfo::PutToLog(Log *log) const { if (log == NULL) return; - const uint8_t *u = (uint8_t *)m_uuid.GetBytes(); + const uint8_t *u = static_cast<const uint8_t *>(m_uuid.GetBytes()); if (m_load_address == LLDB_INVALID_ADDRESS) { if (u) { diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp b/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp index 1ef1be5d0adb3..c49cdc2f11b1e 100644 --- a/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp +++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp @@ -7,10 +7,6 @@ // //===----------------------------------------------------------------------===// -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp index c1986976b0fc4..e601d64f0d8d0 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp @@ -7,10 +7,6 @@ // //===----------------------------------------------------------------------===// -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Symbol.h" @@ -18,6 +14,7 @@ #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" diff --git a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp index c381326ebf4fe..6502d7a7a58ce 100644 --- a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp +++ b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp @@ -11,8 +11,11 @@ #include "DynamicLoaderWindowsDYLD.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" #include "lldb/Target/Target.h" +#include "lldb/Target/ThreadPlanStepInstruction.h" #include "llvm/ADT/Triple.h" @@ -72,5 +75,44 @@ uint32_t DynamicLoaderWindowsDYLD::GetPluginVersion() { return 1; } ThreadPlanSP DynamicLoaderWindowsDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop) { - return ThreadPlanSP(); + auto arch = m_process->GetTarget().GetArchitecture(); + if (arch.GetMachine() != llvm::Triple::x86) { + return ThreadPlanSP(); + } + + uint64_t pc = thread.GetRegisterContext()->GetPC(); + // Max size of an instruction in x86 is 15 bytes. + AddressRange range(pc, 2 * 15); + + ExecutionContext exe_ctx(m_process->GetTarget()); + DisassemblerSP disassembler_sp = Disassembler::DisassembleRange( + arch, nullptr, nullptr, exe_ctx, range, true); + if (!disassembler_sp) { + return ThreadPlanSP(); + } + + InstructionList *insn_list = &disassembler_sp->GetInstructionList(); + if (insn_list == nullptr) { + return ThreadPlanSP(); + } + + // First instruction in a x86 Windows trampoline is going to be an indirect + // jump through the IAT and the next one will be a nop (usually there for + // alignment purposes). e.g.: + // 0x70ff4cfc <+956>: jmpl *0x7100c2a8 + // 0x70ff4d02 <+962>: nop + + auto first_insn = insn_list->GetInstructionAtIndex(0); + auto second_insn = insn_list->GetInstructionAtIndex(1); + + if (first_insn == nullptr || second_insn == nullptr || + strcmp(first_insn->GetMnemonic(&exe_ctx), "jmpl") != 0 || + strcmp(second_insn->GetMnemonic(&exe_ctx), "nop") != 0) { + return ThreadPlanSP(); + } + + assert(first_insn->DoesBranch() && !second_insn->DoesBranch()); + + return ThreadPlanSP(new ThreadPlanStepInstruction( + thread, false, false, eVoteNoOpinion, eVoteNoOpinion)); } diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index 7622791778ba2..7f031356b3c3f 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -51,8 +51,94 @@ private: }; } +ClangASTSource::ClangASTSource(const lldb::TargetSP &target) + : m_import_in_progress(false), m_lookups_enabled(false), m_target(target), + m_ast_context(NULL), m_active_lexical_decls(), m_active_lookups() { + if (!target->GetUseModernTypeLookup()) { + m_ast_importer_sp = m_target->GetClangASTImporter(); + } +} + +void ClangASTSource::InstallASTContext(clang::ASTContext &ast_context, + clang::FileManager &file_manager, + bool is_shared_context) { + m_ast_context = &ast_context; + m_file_manager = &file_manager; + if (m_target->GetUseModernTypeLookup()) { + // Configure the ExternalASTMerger. The merger needs to be able to import + // types from any source that we would do lookups in, which includes the + // persistent AST context as well as the modules and Objective-C runtime + // AST contexts. + + lldbassert(!m_merger_up); + clang::ExternalASTMerger::ImporterTarget target = {ast_context, + file_manager}; + std::vector<clang::ExternalASTMerger::ImporterSource> sources; + for (lldb::ModuleSP module_sp : m_target->GetImages().Modules()) { + if (auto *module_ast_ctx = llvm::cast_or_null<ClangASTContext>( + module_sp->GetTypeSystemForLanguage(lldb::eLanguageTypeC))) { + lldbassert(module_ast_ctx->getASTContext()); + lldbassert(module_ast_ctx->getFileManager()); + sources.push_back({*module_ast_ctx->getASTContext(), + *module_ast_ctx->getFileManager(), + module_ast_ctx->GetOriginMap() + }); + } + } + + do { + lldb::ProcessSP process(m_target->GetProcessSP()); + + if (!process) + break; + + ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); + + if (!language_runtime) + break; + + DeclVendor *runtime_decl_vendor = language_runtime->GetDeclVendor(); + + if (!runtime_decl_vendor) + break; + + sources.push_back(runtime_decl_vendor->GetImporterSource()); + } while (0); + + do { + DeclVendor *modules_decl_vendor = + m_target->GetClangModulesDeclVendor(); + + if (!modules_decl_vendor) + break; + + sources.push_back(modules_decl_vendor->GetImporterSource()); + } while (0); + + if (!is_shared_context) { + // Update the scratch AST context's merger to reflect any new sources we + // might have come across since the last time an expression was parsed. + + auto scratch_ast_context = static_cast<ClangASTContextForExpressions*>( + m_target->GetScratchClangASTContext()); + + scratch_ast_context->GetMergerUnchecked().AddSources(sources); + + sources.push_back({*scratch_ast_context->getASTContext(), + *scratch_ast_context->getFileManager(), + scratch_ast_context->GetOriginMap()}); + } while (0); + + m_merger_up = + llvm::make_unique<clang::ExternalASTMerger>(target, sources); + } else { + m_ast_importer_sp->InstallMapCompleter(&ast_context, *this); + } +} + ClangASTSource::~ClangASTSource() { - m_ast_importer_sp->ForgetDestination(m_ast_context); + if (m_ast_importer_sp) + m_ast_importer_sp->ForgetDestination(m_ast_context); // We are in the process of destruction, don't create clang ast context on // demand @@ -69,7 +155,7 @@ ClangASTSource::~ClangASTSource() { if (!scratch_ast_context) return; - if (m_ast_context != scratch_ast_context) + if (m_ast_context != scratch_ast_context && m_ast_importer_sp) m_ast_importer_sp->ForgetSource(scratch_ast_context, m_ast_context); } @@ -203,6 +289,13 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) { m_active_lexical_decls.insert(tag_decl); ScopedLexicalDeclEraser eraser(m_active_lexical_decls, tag_decl); + if (!m_ast_importer_sp) { + if (HasMerger()) { + GetMergerUnchecked().CompleteType(tag_decl); + } + return; + } + if (!m_ast_importer_sp->CompleteTagDecl(tag_decl)) { // We couldn't complete the type. Maybe there's a definition // somewhere else that can be completed. @@ -337,6 +430,22 @@ void ClangASTSource::CompleteType(clang::ObjCInterfaceDecl *interface_decl) { dumper.ToLog(log, " [COID] "); } + if (!m_ast_importer_sp) { + if (HasMerger()) { + ObjCInterfaceDecl *complete_iface_decl = + GetCompleteObjCInterface(interface_decl); + + if (complete_iface_decl && (complete_iface_decl != interface_decl)) { + m_merger_up->ForceRecordOrigin(interface_decl, {complete_iface_decl, &complete_iface_decl->getASTContext()}); + } + + GetMergerUnchecked().CompleteType(interface_decl); + } else { + lldbassert(0 && "No mechanism for completing a type!"); + } + return; + } + Decl *original_decl = NULL; ASTContext *original_ctx = NULL; @@ -367,7 +476,7 @@ void ClangASTSource::CompleteType(clang::ObjCInterfaceDecl *interface_decl) { } clang::ObjCInterfaceDecl *ClangASTSource::GetCompleteObjCInterface( - clang::ObjCInterfaceDecl *interface_decl) { + const clang::ObjCInterfaceDecl *interface_decl) { lldb::ProcessSP process(m_target->GetProcessSP()); if (!process) @@ -411,6 +520,22 @@ void ClangASTSource::FindExternalLexicalDecls( const DeclContext *decl_context, llvm::function_ref<bool(Decl::Kind)> predicate, llvm::SmallVectorImpl<Decl *> &decls) { + + if (HasMerger()) { + if (auto *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl_context)) { + ObjCInterfaceDecl *complete_iface_decl = + GetCompleteObjCInterface(interface_decl); + + if (complete_iface_decl && (complete_iface_decl != interface_decl)) { + m_merger_up->ForceRecordOrigin(interface_decl, {complete_iface_decl, &complete_iface_decl->getASTContext()}); + } + } + return GetMergerUnchecked().FindExternalLexicalDecls(decl_context, + predicate, + decls); + } else if (!m_ast_importer_sp) + return; + ClangASTMetrics::RegisterLexicalQuery(); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); @@ -507,8 +632,7 @@ void ClangASTSource::FindExternalLexicalDecls( decl->getDeclKindName(), ast_dumper.GetCString()); } - Decl *copied_decl = - m_ast_importer_sp->CopyDecl(m_ast_context, original_ctx, decl); + Decl *copied_decl = CopyDecl(decl); if (!copied_decl) continue; @@ -568,12 +692,31 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { name.GetCString(), context.m_decl_context->getDeclKindName()); } + if (HasMerger() && !isa<TranslationUnitDecl>(context.m_decl_context) + /* possibly handle NamespaceDecls here? */) { + if (auto *interface_decl = + dyn_cast<ObjCInterfaceDecl>(context.m_decl_context)) { + ObjCInterfaceDecl *complete_iface_decl = + GetCompleteObjCInterface(interface_decl); + + if (complete_iface_decl && (complete_iface_decl != interface_decl)) { + GetMergerUnchecked().ForceRecordOrigin( + interface_decl, + {complete_iface_decl, &complete_iface_decl->getASTContext()}); + } + } + + GetMergerUnchecked().FindExternalVisibleDeclsByName(context.m_decl_context, + context.m_decl_name); + return; // otherwise we may need to fall back + } + context.m_namespace_map.reset(new ClangASTImporter::NamespaceMap); if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(context.m_decl_context)) { - ClangASTImporter::NamespaceMapSP namespace_map = - m_ast_importer_sp->GetNamespaceMap(namespace_context); + ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp ? + m_ast_importer_sp->GetNamespaceMap(namespace_context) : nullptr; if (log && log->GetVerbose()) log->Printf(" CAS::FEVD[%u] Inspecting namespace map %p (%d entries)", @@ -593,7 +736,7 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { FindExternalVisibleDecls(context, i->first, i->second, current_id); } - } else if (isa<ObjCInterfaceDecl>(context.m_decl_context)) { + } else if (isa<ObjCInterfaceDecl>(context.m_decl_context) && !HasMerger()) { FindObjCPropertyAndIvarDecls(context); } else if (!isa<TranslationUnitDecl>(context.m_decl_context)) { // we shouldn't be getting FindExternalVisibleDecls calls for these @@ -623,6 +766,25 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { } } +bool ClangASTSource::IgnoreName(const ConstString name, + bool ignore_all_dollar_names) { + static const ConstString id_name("id"); + static const ConstString Class_name("Class"); + + if (name == id_name || name == Class_name) + return true; + + StringRef name_string_ref = name.GetStringRef(); + + // The ClangASTSource is not responsible for finding $-names. + if (name_string_ref.empty() || + (ignore_all_dollar_names && name_string_ref.startswith("$")) || + name_string_ref.startswith("_$")) + return true; + + return false; +} + void ClangASTSource::FindExternalVisibleDecls( NameSearchContext &context, lldb::ModuleSP module_sp, CompilerDeclContext &namespace_decl, unsigned int current_id) { @@ -633,20 +795,7 @@ void ClangASTSource::FindExternalVisibleDecls( SymbolContextList sc_list; const ConstString name(context.m_decl_name.getAsString().c_str()); - - const char *name_unique_cstr = name.GetCString(); - - static ConstString id_name("id"); - static ConstString Class_name("Class"); - - if (name == id_name || name == Class_name) - return; - - if (name_unique_cstr == NULL) - return; - - // The ClangASTSource is not responsible for finding $-names. - if (name_unique_cstr[0] == '$') + if (IgnoreName(name, true)) return; if (module_sp && namespace_decl) { @@ -671,7 +820,7 @@ void ClangASTSource::FindExternalVisibleDecls( module_sp->GetFileSpec().GetFilename().GetCString()); } } - } else { + } else if (!HasMerger()) { const ModuleList &target_images = m_target->GetImages(); std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex()); @@ -774,9 +923,7 @@ void ClangASTSource::FindExternalVisibleDecls( if (llvm::isa<clang::TypeDecl>(decl_from_modules) || llvm::isa<clang::ObjCContainerDecl>(decl_from_modules) || llvm::isa<clang::EnumConstantDecl>(decl_from_modules)) { - clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl( - m_ast_context, &decl_from_modules->getASTContext(), - decl_from_modules); + clang::Decl *copied_decl = CopyDecl(decl_from_modules); clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr; @@ -831,8 +978,7 @@ void ClangASTSource::FindExternalVisibleDecls( current_id, name.GetCString()); } - clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl( - m_ast_context, &decls[0]->getASTContext(), decls[0]); + clang::Decl *copied_decl = CopyDecl(decls[0]); clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr; @@ -875,7 +1021,7 @@ public: DeclFromParser() : TaggedASTDecl<D>() {} DeclFromParser(D *_decl) : TaggedASTDecl<D>(_decl) {} - DeclFromUser<D> GetOrigin(ClangASTImporter *importer); + DeclFromUser<D> GetOrigin(ClangASTSource &source); }; template <class D> class DeclFromUser : public TaggedASTDecl<D> { @@ -883,32 +1029,29 @@ public: DeclFromUser() : TaggedASTDecl<D>() {} DeclFromUser(D *_decl) : TaggedASTDecl<D>(_decl) {} - DeclFromParser<D> Import(ClangASTImporter *importer, ASTContext &dest_ctx); + DeclFromParser<D> Import(ClangASTSource &source); }; template <class D> -DeclFromUser<D> DeclFromParser<D>::GetOrigin(ClangASTImporter *importer) { +DeclFromUser<D> DeclFromParser<D>::GetOrigin(ClangASTSource &source) { DeclFromUser<> origin_decl; - importer->ResolveDeclOrigin(this->decl, &origin_decl.decl, NULL); + source.ResolveDeclOrigin(this->decl, &origin_decl.decl, NULL); if (origin_decl.IsInvalid()) return DeclFromUser<D>(); return DeclFromUser<D>(dyn_cast<D>(origin_decl.decl)); } template <class D> -DeclFromParser<D> DeclFromUser<D>::Import(ClangASTImporter *importer, - ASTContext &dest_ctx) { - DeclFromParser<> parser_generic_decl( - importer->CopyDecl(&dest_ctx, &this->decl->getASTContext(), this->decl)); +DeclFromParser<D> DeclFromUser<D>::Import(ClangASTSource &source) { + DeclFromParser<> parser_generic_decl(source.CopyDecl(this->decl)); if (parser_generic_decl.IsInvalid()) return DeclFromParser<D>(); return DeclFromParser<D>(dyn_cast<D>(parser_generic_decl.decl)); } -static bool FindObjCMethodDeclsWithOrigin( +bool ClangASTSource::FindObjCMethodDeclsWithOrigin( unsigned int current_id, NameSearchContext &context, - ObjCInterfaceDecl *original_interface_decl, clang::ASTContext *ast_context, - ClangASTImporter *ast_importer, const char *log_info) { + ObjCInterfaceDecl *original_interface_decl, const char *log_info) { const DeclarationName &decl_name(context.m_decl_name); clang::ASTContext *original_ctx = &original_interface_decl->getASTContext(); @@ -967,8 +1110,7 @@ static bool FindObjCMethodDeclsWithOrigin( if (!result_method) continue; - Decl *copied_decl = ast_importer->CopyDecl( - ast_context, &result_method->getASTContext(), result_method); + Decl *copied_decl = CopyDecl(result_method); if (!copied_decl) continue; @@ -995,6 +1137,21 @@ static bool FindObjCMethodDeclsWithOrigin( void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + if (HasMerger()) { + if (auto *interface_decl = dyn_cast<ObjCInterfaceDecl>(context.m_decl_context)) { + ObjCInterfaceDecl *complete_iface_decl = + GetCompleteObjCInterface(interface_decl); + + if (complete_iface_decl && (complete_iface_decl != context.m_decl_context)) { + m_merger_up->ForceRecordOrigin(interface_decl, {complete_iface_decl, &complete_iface_decl->getASTContext()}); + } + } + + GetMergerUnchecked().FindExternalVisibleDeclsByName(context.m_decl_context, + context.m_decl_name); + return; + } + static unsigned int invocation_id = 0; unsigned int current_id = invocation_id++; @@ -1021,8 +1178,7 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { dyn_cast<ObjCInterfaceDecl>(original_decl); if (FindObjCMethodDeclsWithOrigin(current_id, context, - original_interface_decl, m_ast_context, - m_ast_importer_sp.get(), "at origin")) + original_interface_decl, "at origin")) return; // found it, no need to look any further } while (0); @@ -1160,8 +1316,7 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { continue; if (found_interface_decl->getName() == interface_decl->getName()) { - Decl *copied_decl = m_ast_importer_sp->CopyDecl( - m_ast_context, &method_decl->getASTContext(), method_decl); + Decl *copied_decl = CopyDecl(method_decl); if (!copied_decl) continue; @@ -1210,7 +1365,6 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { static_cast<void *>(&complete_iface_decl->getASTContext())); FindObjCMethodDeclsWithOrigin(current_id, context, complete_interface_decl, - m_ast_context, m_ast_importer_sp.get(), "in debug info"); return; @@ -1238,8 +1392,7 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { break; if (FindObjCMethodDeclsWithOrigin( - current_id, context, interface_decl_from_modules, m_ast_context, - m_ast_importer_sp.get(), "in modules")) + current_id, context, interface_decl_from_modules, "in modules")) return; } } while (0); @@ -1278,14 +1431,12 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { break; FindObjCMethodDeclsWithOrigin(current_id, context, runtime_interface_decl, - m_ast_context, m_ast_importer_sp.get(), "in runtime"); } while (0); } static bool FindObjCPropertyAndIvarDeclsWithOrigin( - unsigned int current_id, NameSearchContext &context, - clang::ASTContext &ast_context, ClangASTImporter *ast_importer, + unsigned int current_id, NameSearchContext &context, ClangASTSource &source, DeclFromUser<const ObjCInterfaceDecl> &origin_iface_decl) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); @@ -1305,7 +1456,7 @@ static bool FindObjCPropertyAndIvarDeclsWithOrigin( if (origin_property_decl.IsValid()) { DeclFromParser<ObjCPropertyDecl> parser_property_decl( - origin_property_decl.Import(ast_importer, ast_context)); + origin_property_decl.Import(source)); if (parser_property_decl.IsValid()) { if (log) { ASTDumper dumper((Decl *)parser_property_decl.decl); @@ -1323,7 +1474,7 @@ static bool FindObjCPropertyAndIvarDeclsWithOrigin( if (origin_ivar_decl.IsValid()) { DeclFromParser<ObjCIvarDecl> parser_ivar_decl( - origin_ivar_decl.Import(ast_importer, ast_context)); + origin_ivar_decl.Import(source)); if (parser_ivar_decl.IsValid()) { if (log) { ASTDumper dumper((Decl *)parser_ivar_decl.decl); @@ -1348,7 +1499,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { DeclFromParser<const ObjCInterfaceDecl> parser_iface_decl( cast<ObjCInterfaceDecl>(context.m_decl_context)); DeclFromUser<const ObjCInterfaceDecl> origin_iface_decl( - parser_iface_decl.GetOrigin(m_ast_importer_sp.get())); + parser_iface_decl.GetOrigin(*this)); ConstString class_name(parser_iface_decl->getNameAsString().c_str()); @@ -1360,8 +1511,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { context.m_decl_name.getAsString().c_str()); if (FindObjCPropertyAndIvarDeclsWithOrigin( - current_id, context, *m_ast_context, m_ast_importer_sp.get(), - origin_iface_decl)) + current_id, context, *this, origin_iface_decl)) return; if (log) @@ -1397,8 +1547,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { static_cast<const void *>(complete_iface_decl.decl), static_cast<void *>(&complete_iface_decl->getASTContext())); - FindObjCPropertyAndIvarDeclsWithOrigin(current_id, context, *m_ast_context, - m_ast_importer_sp.get(), + FindObjCPropertyAndIvarDeclsWithOrigin(current_id, context, *this, complete_iface_decl); return; @@ -1435,9 +1584,8 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { static_cast<const void *>(interface_decl_from_modules.decl), static_cast<void *>(&interface_decl_from_modules->getASTContext())); - if (FindObjCPropertyAndIvarDeclsWithOrigin( - current_id, context, *m_ast_context, m_ast_importer_sp.get(), - interface_decl_from_modules)) + if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, context, *this, + interface_decl_from_modules)) return; } while (0); @@ -1483,8 +1631,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { static_cast<void *>(&interface_decl_from_runtime->getASTContext())); if (FindObjCPropertyAndIvarDeclsWithOrigin( - current_id, context, *m_ast_context, m_ast_importer_sp.get(), - interface_decl_from_runtime)) + current_id, context, *this, interface_decl_from_runtime)) return; } while (0); } @@ -1495,7 +1642,7 @@ typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetMap; template <class D, class O> static bool ImportOffsetMap(llvm::DenseMap<const D *, O> &destination_map, llvm::DenseMap<const D *, O> &source_map, - ClangASTImporter *importer, ASTContext &dest_ctx) { + ClangASTSource &source) { // When importing fields into a new record, clang has a hard requirement that // fields be imported in field offset order. Since they are stored in a // DenseMap @@ -1516,7 +1663,7 @@ static bool ImportOffsetMap(llvm::DenseMap<const D *, O> &destination_map, for (const auto &item : sorted_items) { DeclFromUser<D> user_decl(const_cast<D *>(item.first)); - DeclFromParser<D> parser_decl(user_decl.Import(importer, dest_ctx)); + DeclFromParser<D> parser_decl(user_decl.Import(source)); if (parser_decl.IsInvalid()) return false; destination_map.insert( @@ -1593,7 +1740,7 @@ bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, DeclFromParser<const RecordDecl> parser_record(record); DeclFromUser<const RecordDecl> origin_record( - parser_record.GetOrigin(m_ast_importer_sp.get())); + parser_record.GetOrigin(*this)); if (origin_record.IsInvalid()) return false; @@ -1629,7 +1776,7 @@ bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, field_idx++; } - ASTContext &parser_ast_context(record->getASTContext()); + lldbassert(&record->getASTContext() == m_ast_context); DeclFromUser<const CXXRecordDecl> origin_cxx_record( DynCast<const CXXRecordDecl>(origin_record)); @@ -1642,12 +1789,10 @@ bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, return false; } - if (!ImportOffsetMap(field_offsets, origin_field_offsets, - m_ast_importer_sp.get(), parser_ast_context) || - !ImportOffsetMap(base_offsets, origin_base_offsets, - m_ast_importer_sp.get(), parser_ast_context) || + if (!ImportOffsetMap(field_offsets, origin_field_offsets, *this) || + !ImportOffsetMap(base_offsets, origin_base_offsets, *this) || !ImportOffsetMap(virtual_base_offsets, origin_virtual_base_offsets, - m_ast_importer_sp.get(), parser_ast_context)) + *this)) return false; size = record_layout.getSize().getQuantity() * m_ast_context->getCharWidth(); @@ -1811,8 +1956,7 @@ NamespaceDecl *ClangASTSource::AddNamespace( if (!src_namespace_decl) return nullptr; - Decl *copied_decl = - m_ast_importer_sp->CopyDecl(m_ast_context, src_ast, src_namespace_decl); + Decl *copied_decl = CopyDecl(src_namespace_decl); if (!copied_decl) return nullptr; @@ -1830,6 +1974,54 @@ NamespaceDecl *ClangASTSource::AddNamespace( return dyn_cast<NamespaceDecl>(copied_decl); } +clang::QualType ClangASTSource::CopyTypeWithMerger( + clang::ASTContext &from_context, + clang::ExternalASTMerger &merger, + clang::QualType type) { + if (!merger.HasImporterForOrigin(from_context)) { + lldbassert(0 && "Couldn't find the importer for a source context!"); + return QualType(); + } + + return merger.ImporterForOrigin(from_context).Import(type); +} + +clang::Decl *ClangASTSource::CopyDecl(Decl *src_decl) { + clang::ASTContext &from_context = src_decl->getASTContext(); + if (m_ast_importer_sp) { + return m_ast_importer_sp->CopyDecl(m_ast_context, &from_context, src_decl); + } else if (m_merger_up) { + if (!m_merger_up->HasImporterForOrigin(from_context)) { + lldbassert(0 && "Couldn't find the importer for a source context!"); + return nullptr; + } + + return m_merger_up->ImporterForOrigin(from_context).Import(src_decl); + } else { + lldbassert(0 && "No mechanism for copying a decl!"); + return nullptr; + } +} + +bool ClangASTSource::ResolveDeclOrigin(const clang::Decl *decl, + clang::Decl **original_decl, + clang::ASTContext **original_ctx) { + if (m_ast_importer_sp) { + return m_ast_importer_sp->ResolveDeclOrigin(decl, original_decl, + original_ctx); + } else if (m_merger_up) { + return false; // Implement this correctly in ExternalASTMerger + } else { + // this can happen early enough that no ExternalASTSource is installed. + return false; + } +} + +clang::ExternalASTMerger &ClangASTSource::GetMergerUnchecked() { + lldbassert(m_merger_up != nullptr); + return *m_merger_up; +} + CompilerType ClangASTSource::GuardedCopyType(const CompilerType &src_type) { ClangASTContext *src_ast = llvm::dyn_cast_or_null<ClangASTContext>(src_type.GetTypeSystem()); @@ -1840,9 +2032,20 @@ CompilerType ClangASTSource::GuardedCopyType(const CompilerType &src_type) { SetImportInProgress(true); - QualType copied_qual_type = - m_ast_importer_sp->CopyType(m_ast_context, src_ast->getASTContext(), - ClangUtil::GetQualType(src_type)); + QualType copied_qual_type; + + if (m_ast_importer_sp) { + copied_qual_type = + m_ast_importer_sp->CopyType(m_ast_context, src_ast->getASTContext(), + ClangUtil::GetQualType(src_type)); + } else if (m_merger_up) { + copied_qual_type = + CopyTypeWithMerger(*src_ast->getASTContext(), *m_merger_up, + ClangUtil::GetQualType(src_type)); + } else { + lldbassert(0 && "No mechanism for copying a type!"); + return CompilerType(); + } SetImportInProgress(false); diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/source/Plugins/ExpressionParser/Clang/ClangASTSource.h index 6362f04cf4886..6f72ad92dc8c0 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangASTSource.h +++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.h @@ -16,6 +16,7 @@ #include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Target/Target.h" +#include "clang/AST/ExternalASTMerger.h" #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/SmallSet.h" @@ -41,14 +42,10 @@ public: /// /// Initializes class variables. /// - /// @param[in] declMap - /// A reference to the LLDB object that handles entity lookup. + /// @param[in] target + /// A reference to the target containing debug information to use. //------------------------------------------------------------------ - ClangASTSource(const lldb::TargetSP &target) - : m_import_in_progress(false), m_lookups_enabled(false), m_target(target), - m_ast_context(NULL), m_active_lexical_decls(), m_active_lookups() { - m_ast_importer_sp = m_target->GetClangASTImporter(); - } + ClangASTSource(const lldb::TargetSP &target); //------------------------------------------------------------------ /// Destructor @@ -70,10 +67,9 @@ public: } void MaterializeVisibleDecls(const clang::DeclContext *DC) { return; } - void InstallASTContext(clang::ASTContext *ast_context) { - m_ast_context = ast_context; - m_ast_importer_sp->InstallMapCompleter(ast_context, *this); - } + void InstallASTContext(clang::ASTContext &ast_context, + clang::FileManager &file_manager, + bool is_shared_context = false); // // APIs for ExternalASTSource @@ -313,7 +309,7 @@ protected: /// the complete interface otherwise. //------------------------------------------------------------------ clang::ObjCInterfaceDecl * - GetCompleteObjCInterface(clang::ObjCInterfaceDecl *interface_decl); + GetCompleteObjCInterface(const clang::ObjCInterfaceDecl *interface_decl); //------------------------------------------------------------------ /// Find all entities matching a given name in a given module, @@ -376,6 +372,89 @@ protected: //------------------------------------------------------------------ CompilerType GuardedCopyType(const CompilerType &src_type); +public: + //------------------------------------------------------------------ + /// Returns true if a name should be ignored by name lookup. + /// + /// @param[in] name + /// The name to be considered. + /// + /// @param[in] ignore_all_dollar_nmmes + /// True if $-names of all sorts should be ignored. + /// + /// @return + /// True if the name is one of a class of names that are ignored by + /// global lookup for performance reasons. + //------------------------------------------------------------------ + bool IgnoreName(const ConstString name, bool ignore_all_dollar_names); + +public: + //------------------------------------------------------------------ + /// Copies a single Decl into the parser's AST context. + /// + /// @param[in] src_decl + /// The Decl to copy. + /// + /// @return + /// A copy of the Decl in m_ast_context, or NULL if the copy failed. + //------------------------------------------------------------------ + clang::Decl *CopyDecl(clang::Decl *src_decl); + + //------------------------------------------------------------------ + /// Copies a single Type to the target of the given ExternalASTMerger. + /// + /// @param[in] src_context + /// The ASTContext containing the type. + /// + /// @param[in] merger + /// The merger to use. This isn't just *m_merger_up because it might be + /// the persistent AST context's merger. + /// + /// @param[in] type + /// The type to copy. + /// + /// @return + /// A copy of the Type in the merger's target context. + //------------------------------------------------------------------ + clang::QualType CopyTypeWithMerger(clang::ASTContext &src_context, + clang::ExternalASTMerger &merger, + clang::QualType type); + + //------------------------------------------------------------------ + /// Determined the origin of a single Decl, if it can be found. + /// + /// @param[in] decl + /// The Decl whose origin is to be found. + /// + /// @param[out] original_decl + /// A pointer whose target is filled in with the original Decl. + /// + /// @param[in] original_ctx + /// A pointer whose target is filled in with the original's ASTContext. + /// + /// @return + /// True if lookup succeeded; false otherwise. + //------------------------------------------------------------------ + bool ResolveDeclOrigin(const clang::Decl *decl, clang::Decl **original_decl, + clang::ASTContext **original_ctx); + + //------------------------------------------------------------------ + /// Returns m_merger_up. Only call this if the target is configured to use + /// modern lookup, + //------------------------------------------------------------------ + clang::ExternalASTMerger &GetMergerUnchecked(); + + //------------------------------------------------------------------ + /// Returns true if there is a merger. This only occurs if the target is + /// using modern lookup. + //------------------------------------------------------------------ + bool HasMerger() { return (bool)m_merger_up; } + +protected: + bool FindObjCMethodDeclsWithOrigin( + unsigned int current_id, NameSearchContext &context, + clang::ObjCInterfaceDecl *original_interface_decl, const char *log_info); + friend struct NameSearchContext; bool m_import_in_progress; @@ -385,7 +464,11 @@ protected: m_target; ///< The target to use in finding variables and types. clang::ASTContext *m_ast_context; ///< The AST context requests are coming in for. + clang::FileManager + *m_file_manager; ///< The file manager paired with the AST context. lldb::ClangASTImporterSP m_ast_importer_sp; ///< The target's AST importer. + std::unique_ptr<clang::ExternalASTMerger> m_merger_up; + ///< The ExternalASTMerger for this parse. std::set<const clang::Decl *> m_active_lexical_decls; std::set<const char *> m_active_lookups; }; diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 8fde41052192b..07ff2e97aac77 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -48,8 +48,10 @@ #include "lldb/lldb-private.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTImporter.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclarationName.h" +#include "clang/AST/RecursiveASTVisitor.h" #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" @@ -178,6 +180,134 @@ ClangExpressionDeclMap::TargetInfo ClangExpressionDeclMap::GetTargetInfo() { return ret; } +namespace { +/// This class walks an AST and ensures that all DeclContexts defined inside the +/// current source file are properly complete. +/// +/// This is used to ensure that persistent types defined in the current source +/// file migrate completely to the persistent AST context before they are +/// reused. If that didn't happen, it would be impoossible to complete them +/// because their origin would be gone. +/// +/// The stragtegy used by this class is to check the SourceLocation (to be +/// specific, the FileID) and see if it's the FileID for the current expression. +/// Alternate strategies could include checking whether an ExternalASTMerger, +/// set up to not have the current context as a source, can find an original for +/// the type. +class Completer : public clang::RecursiveASTVisitor<Completer> { +private: + clang::ASTImporter &m_exporter; /// Used to import Decl contents + clang::FileID m_file; /// The file that's going away + llvm::DenseSet<clang::Decl *> m_completed; /// Visited Decls, to avoid cycles + + bool ImportAndCheckCompletable(clang::Decl *decl) { + (void)m_exporter.Import(decl); + if (m_completed.count(decl)) + return false; + if (!llvm::isa<DeclContext>(decl)) + return false; + const clang::SourceLocation loc = decl->getLocation(); + if (!loc.isValid()) + return false; + const clang::FileID file = + m_exporter.getFromContext().getSourceManager().getFileID(loc); + if (file != m_file) + return false; + // We are assuming the Decl was parsed in this very expression, so it should + // not have external storage. + lldbassert(!llvm::cast<DeclContext>(decl)->hasExternalLexicalStorage()); + return true; + } + + void Complete(clang::Decl *decl) { + m_completed.insert(decl); + auto *decl_context = llvm::cast<DeclContext>(decl); + (void)m_exporter.Import(decl); + m_exporter.CompleteDecl(decl); + for (Decl *child : decl_context->decls()) + if (ImportAndCheckCompletable(child)) + Complete(child); + } + + void MaybeComplete(clang::Decl *decl) { + if (ImportAndCheckCompletable(decl)) + Complete(decl); + } + +public: + Completer(clang::ASTImporter &exporter, clang::FileID file) + : m_exporter(exporter), m_file(file) {} + + // Implements the RecursiveASTVisitor's core API. It is called on each Decl + // that the RecursiveASTVisitor encounters, and returns true if the traversal + // should continue. + bool VisitDecl(clang::Decl *decl) { + MaybeComplete(decl); + return true; + } +}; +} + +static void CompleteAllDeclContexts(clang::ASTImporter &exporter, + clang::FileID file, + clang::QualType root) { + clang::QualType canonical_type = root.getCanonicalType(); + if (clang::TagDecl *tag_decl = canonical_type->getAsTagDecl()) { + Completer(exporter, file).TraverseDecl(tag_decl); + } else if (auto interface_type = llvm::dyn_cast<ObjCInterfaceType>( + canonical_type.getTypePtr())) { + Completer(exporter, file).TraverseDecl(interface_type->getDecl()); + } else { + Completer(exporter, file).TraverseType(canonical_type); + } +} + +static clang::QualType ExportAllDeclaredTypes( + clang::ExternalASTMerger &merger, + clang::ASTContext &source, clang::FileManager &source_file_manager, + const clang::ExternalASTMerger::OriginMap &source_origin_map, + clang::FileID file, clang::QualType root) { + clang::ExternalASTMerger::ImporterSource importer_source = + { source, source_file_manager, source_origin_map }; + merger.AddSources(importer_source); + clang::ASTImporter &exporter = merger.ImporterForOrigin(source); + CompleteAllDeclContexts(exporter, file, root); + clang::QualType ret = exporter.Import(root); + merger.RemoveSources(importer_source); + return ret; +} + +TypeFromUser ClangExpressionDeclMap::DeportType(ClangASTContext &target, + ClangASTContext &source, + TypeFromParser parser_type) { + assert (&target == m_target->GetScratchClangASTContext()); + assert ((TypeSystem*)&source == parser_type.GetTypeSystem()); + assert (source.getASTContext() == m_ast_context); + + if (m_ast_importer_sp) { + return TypeFromUser(m_ast_importer_sp->DeportType( + target.getASTContext(), source.getASTContext(), + parser_type.GetOpaqueQualType()), + &target); + } else if (m_merger_up) { + clang::FileID source_file = + source.getASTContext()->getSourceManager().getFileID( + source.getASTContext()->getTranslationUnitDecl()->getLocation()); + auto scratch_ast_context = static_cast<ClangASTContextForExpressions*>( + m_target->GetScratchClangASTContext()); + clang::QualType exported_type = ExportAllDeclaredTypes( + scratch_ast_context->GetMergerUnchecked(), + *source.getASTContext(), *source.getFileManager(), + m_merger_up->GetOrigins(), + source_file, + clang::QualType::getFromOpaquePtr(parser_type.GetOpaqueQualType())); + return TypeFromUser(exported_type.getAsOpaquePtr(), &target); + } else { + lldbassert(0 && "No mechanism for deporting a type!"); + return TypeFromUser(); + } +} + bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl, const ConstString &name, TypeFromParser parser_type, @@ -198,12 +328,8 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl, if (target == nullptr) return false; - ClangASTContext *context(target->GetScratchClangASTContext()); - - TypeFromUser user_type(m_ast_importer_sp->DeportType( - context->getASTContext(), ast->getASTContext(), - parser_type.GetOpaqueQualType()), - context); + TypeFromUser user_type = + DeportType(*target->GetScratchClangASTContext(), *ast, parser_type); uint32_t offset = m_parser_vars->m_materializer->AddResultVariable( user_type, is_lvalue, m_keep_result_in_memory, m_result_delegate, err); @@ -240,10 +366,7 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl, ClangASTContext *context(target->GetScratchClangASTContext()); - TypeFromUser user_type(m_ast_importer_sp->DeportType( - context->getASTContext(), ast->getASTContext(), - parser_type.GetOpaqueQualType()), - context); + TypeFromUser user_type = DeportType(*context, *ast, parser_type); if (!user_type.GetOpaqueQualType()) { if (log) @@ -688,16 +811,18 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( } ClangASTImporter::NamespaceMapSP namespace_map = - m_ast_importer_sp->GetNamespaceMap(namespace_context); + m_ast_importer_sp + ? m_ast_importer_sp->GetNamespaceMap(namespace_context) + : ClangASTImporter::NamespaceMapSP(); + + if (!namespace_map) + return; if (log && log->GetVerbose()) log->Printf(" CEDM::FEVD[%u] Inspecting (NamespaceMap*)%p (%d entries)", current_id, static_cast<void *>(namespace_map.get()), (int)namespace_map->size()); - - if (!namespace_map) - return; - + for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); i != e; ++i) { @@ -739,16 +864,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( SymbolContextList sc_list; const ConstString name(context.m_decl_name.getAsString().c_str()); - - const char *name_unique_cstr = name.GetCString(); - - if (name_unique_cstr == NULL) - return; - - static ConstString id_name("id"); - static ConstString Class_name("Class"); - - if (name == id_name || name == Class_name) + if (IgnoreName(name, false)) return; // Only look for functions by name out in our symbols if the function @@ -784,8 +900,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (!persistent_decl) break; - Decl *parser_persistent_decl = m_ast_importer_sp->CopyDecl( - m_ast_context, scratch_ast_context, persistent_decl); + Decl *parser_persistent_decl = CopyDecl(persistent_decl); if (!parser_persistent_decl) break; @@ -809,7 +924,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( } while (0); } - if (name_unique_cstr[0] == '$' && !namespace_decl) { + if (name.GetCString()[0] == '$' && !namespace_decl) { static ConstString g_lldb_class_name("$__lldb_class"); if (name == g_lldb_class_name) { @@ -1041,7 +1156,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (ast) { clang::NamespaceDecl *namespace_decl = ClangASTContext::GetUniqueNamespaceDeclaration( - m_ast_context, name_unique_cstr, nullptr); + m_ast_context, name.GetCString(), nullptr); if (namespace_decl) { context.AddNamedDecl(namespace_decl); clang::DeclContext *clang_decl_ctx = @@ -1056,7 +1171,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( } // any other $__lldb names should be weeded out now - if (!::strncmp(name_unique_cstr, "$__lldb", sizeof("$__lldb") - 1)) + if (name.GetStringRef().startswith("$__lldb")) return; ExpressionVariableSP pvar_sp( @@ -1329,8 +1444,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( for (clang::NamedDecl *decl : decls_from_modules) { if (llvm::isa<clang::FunctionDecl>(decl)) { clang::NamedDecl *copied_decl = - llvm::cast_or_null<FunctionDecl>(m_ast_importer_sp->CopyDecl( - m_ast_context, &decl->getASTContext(), decl)); + llvm::cast_or_null<FunctionDecl>(CopyDecl(decl)); if (copied_decl) { context.AddNamedDecl(copied_decl); context.m_found.function_with_type_info = true; @@ -1372,9 +1486,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( current_id, name.GetCString()); } - clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl( - m_ast_context, &decl_from_modules->getASTContext(), - decl_from_modules); + clang::Decl *copied_decl = CopyDecl(decl_from_modules); clang::FunctionDecl *copied_function_decl = copied_decl ? dyn_cast<clang::FunctionDecl>(copied_decl) : nullptr; @@ -1401,9 +1513,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( current_id, name.GetCString()); } - clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl( - m_ast_context, &decl_from_modules->getASTContext(), - decl_from_modules); + clang::Decl *copied_decl = CopyDecl(decl_from_modules); clang::VarDecl *copied_var_decl = copied_decl ? dyn_cast_or_null<clang::VarDecl>(copied_decl) : nullptr; @@ -1430,17 +1540,17 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( // a generic // data symbol, and -- if it is found -- treat it as a variable. Status error; - + const Symbol *data_symbol = m_parser_vars->m_sym_ctx.FindBestGlobalDataSymbol(name, error); - + if (!error.Success()) { const unsigned diag_id = m_ast_context->getDiagnostics().getCustomDiagID( clang::DiagnosticsEngine::Level::Error, "%0"); m_ast_context->getDiagnostics().Report(diag_id) << error.AsCString(); } - + if (data_symbol) { std::string warning("got name from symbols: "); warning.append(name.AsCString()); @@ -1455,49 +1565,6 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( } } -// static opaque_compiler_type_t -// MaybePromoteToBlockPointerType -//( -// ASTContext *ast_context, -// opaque_compiler_type_t candidate_type -//) -//{ -// if (!candidate_type) -// return candidate_type; -// -// QualType candidate_qual_type = QualType::getFromOpaquePtr(candidate_type); -// -// const PointerType *candidate_pointer_type = -// dyn_cast<PointerType>(candidate_qual_type); -// -// if (!candidate_pointer_type) -// return candidate_type; -// -// QualType pointee_qual_type = candidate_pointer_type->getPointeeType(); -// -// const RecordType *pointee_record_type = -// dyn_cast<RecordType>(pointee_qual_type); -// -// if (!pointee_record_type) -// return candidate_type; -// -// RecordDecl *pointee_record_decl = pointee_record_type->getDecl(); -// -// if (!pointee_record_decl->isRecord()) -// return candidate_type; -// -// if -// (!pointee_record_decl->getName().startswith(llvm::StringRef("__block_literal_"))) -// return candidate_type; -// -// QualType generic_function_type = -// ast_context->getFunctionNoProtoType(ast_context->UnknownAnyTy); -// QualType block_pointer_type = -// ast_context->getBlockPointerType(generic_function_type); -// -// return block_pointer_type.getAsOpaquePtr(); -//} - bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var, lldb_private::Value &var_location, TypeFromUser *user_type, @@ -1537,7 +1604,6 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var, "There is no AST context for the current execution context"); return false; } - // var_clang_type = MaybePromoteToBlockPointerType (ast, var_clang_type); DWARFExpression &var_location_expr = var->LocationExpression(); @@ -1762,7 +1828,9 @@ bool ClangExpressionDeclMap::ResolveUnknownTypes() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - ClangASTContext *scratch_ast_context = target->GetScratchClangASTContext(); + ClangASTContextForExpressions *scratch_ast_context = + static_cast<ClangASTContextForExpressions*>( + target->GetScratchClangASTContext()); for (size_t index = 0, num_entities = m_found_entities.GetSize(); index < num_entities; ++index) { @@ -1793,9 +1861,20 @@ bool ClangExpressionDeclMap::ResolveUnknownTypes() { var_type.getAsOpaquePtr(), ClangASTContext::GetASTContext(&var_decl->getASTContext())); - lldb::opaque_compiler_type_t copied_type = m_ast_importer_sp->CopyType( - scratch_ast_context->getASTContext(), &var_decl->getASTContext(), - var_type.getAsOpaquePtr()); + lldb::opaque_compiler_type_t copied_type = 0; + if (m_ast_importer_sp) { + copied_type = m_ast_importer_sp->CopyType( + scratch_ast_context->getASTContext(), &var_decl->getASTContext(), + var_type.getAsOpaquePtr()); + } else if (HasMerger()) { + copied_type = CopyTypeWithMerger( + var_decl->getASTContext(), + scratch_ast_context->GetMergerUnchecked(), + var_type).getAsOpaquePtr(); + } else { + lldbassert(0 && "No mechanism to copy a resolved unknown type!"); + return false; + } if (!copied_type) { if (log) @@ -1892,8 +1971,7 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, if (!extern_c) { TypeSystem *type_system = function->GetDeclContext().GetTypeSystem(); - if (ClangASTContext *src_ast = - llvm::dyn_cast<ClangASTContext>(type_system)) { + if (llvm::isa<ClangASTContext>(type_system)) { clang::DeclContext *src_decl_context = (clang::DeclContext *)function->GetDeclContext() .GetOpaqueDeclContext(); @@ -1905,9 +1983,7 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, src_function_decl->getTemplateSpecializationInfo()->getTemplate(); clang::FunctionTemplateDecl *copied_function_template = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>( - m_ast_importer_sp->CopyDecl(m_ast_context, - src_ast->getASTContext(), - function_template)); + CopyDecl(function_template)); if (copied_function_template) { if (log) { ASTDumper ast_dumper((clang::Decl *)copied_function_template); @@ -1928,9 +2004,7 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, } else if (src_function_decl) { if (clang::FunctionDecl *copied_function_decl = llvm::dyn_cast_or_null<clang::FunctionDecl>( - m_ast_importer_sp->CopyDecl(m_ast_context, - src_ast->getASTContext(), - src_function_decl))) { + CopyDecl(src_function_decl))) { if (log) { ASTDumper ast_dumper((clang::Decl *)copied_function_decl); diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h index e8a9ba6862db7..d163ad4f7e29a 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -613,6 +613,23 @@ private: void AddThisType(NameSearchContext &context, TypeFromUser &type, unsigned int current_id); + //------------------------------------------------------------------ + /// Move a type out of the current ASTContext into another, but make sure to + /// export all components of the type also. + /// + /// @param[in] target + /// The ClangASTContext to move to. + /// @param[in] source + /// The ClangASTContext to move from. This is assumed to be going away. + /// @param[in] parser_type + /// The type as it appears in the source context. + /// + /// @return + /// Returns the moved type, or an empty type if there was a problem. + //------------------------------------------------------------------ + TypeFromUser DeportType(ClangASTContext &target, ClangASTContext &source, + TypeFromParser parser_type); + ClangASTContext *GetClangASTContext(); }; diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index 4e20be79f68b7..d9e53074b3fbc 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -66,7 +66,6 @@ #include "ClangPersistentVariables.h" #include "IRForTarget.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/Module.h" @@ -351,7 +350,6 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope, LLDB_LOGV(log, "LinkerVersion: '{0}'", opts.LinkerVersion); StringList::LogDump(log, opts.FeaturesAsWritten, "FeaturesAsWritten"); StringList::LogDump(log, opts.Features, "Features"); - StringList::LogDump(log, opts.Reciprocals, "Reciprocals"); } // 4. Create and install the target on the compiler. @@ -391,6 +389,14 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope, // FIXME: the following language option is a temporary workaround, // to "ask for ObjC, get ObjC++" (see comment above). m_compiler->getLangOpts().CPlusPlus = true; + + // Clang now sets as default C++14 as the default standard (with + // GNU extensions), so we do the same here to avoid mismatches that + // cause compiler error when evaluating expressions (e.g. nullptr + // not found as it's a C++11 feature). Currently lldb evaluates + // C++14 as C++11 (see two lines below) so we decide to be consistent + // with that, but this could be re-evaluated in the future. + m_compiler->getLangOpts().CPlusPlus11 = true; break; case lldb::eLanguageTypeC_plus_plus: case lldb::eLanguageTypeC_plus_plus_11: @@ -526,7 +532,7 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope, if (decl_map) { llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source( decl_map->CreateProxy()); - decl_map->InstallASTContext(ast_context.get()); + decl_map->InstallASTContext(*ast_context, m_compiler->getFileManager()); ast_context->setExternalSource(ast_source); } diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h index 3e6a109a4af38..41f290f2e127c 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h @@ -10,10 +10,10 @@ #ifndef liblldb_ClangExpressionParser_h_ #define liblldb_ClangExpressionParser_h_ -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/ClangForward.h" #include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionParser.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Status.h" #include "lldb/lldb-public.h" diff --git a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h index 56d1d8412f786..0596d8fde7b9e 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h +++ b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h @@ -17,7 +17,6 @@ #include "ClangExpressionHelper.h" #include "lldb/Core/Address.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/ClangForward.h" #include "lldb/Core/Value.h" #include "lldb/Core/ValueObjectList.h" diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp index bce0eaf6d57e4..b42ceb9afee89 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -85,6 +85,7 @@ public: void ForEachMacro(const ModuleVector &modules, std::function<bool(const std::string &)> handler) override; + clang::ExternalASTMerger::ImporterSource GetImporterSource() override; private: void ReportModuleExportsHelper(std::set<ClangModulesDeclVendor::ModuleID> &exports, @@ -109,6 +110,7 @@ private: typedef std::set<ModuleID> ImportedModuleSet; ImportedModuleMap m_imported_modules; ImportedModuleSet m_user_imported_modules; + const clang::ExternalASTMerger::OriginMap m_origin_map; }; } // anonymous namespace @@ -548,6 +550,12 @@ ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path, is_inclusion_directive); } +clang::ExternalASTMerger::ImporterSource +ClangModulesDeclVendorImpl::GetImporterSource() { + return {m_compiler_instance->getASTContext(), + m_compiler_instance->getFileManager(), m_origin_map}; +} + static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer"; lldb_private::ClangModulesDeclVendor * diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h index fbabcd736865a..23769ccfb0c04 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h +++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h @@ -10,7 +10,6 @@ #ifndef liblldb_ClangModulesDeclVendor_h #define liblldb_ClangModulesDeclVendor_h -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/ClangForward.h" #include "lldb/Symbol/DeclVendor.h" #include "lldb/Target/Platform.h" diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 2a6261a6df4d4..18fe8b49227bd 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -347,7 +347,6 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, // ApplyObjcCastHack(m_expr_text); - // ApplyUnicharHack(m_expr_text); std::string prefix = m_expr_prefix; diff --git a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp index 065e5db4c9f84..0f2aeef27e571 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp @@ -138,15 +138,6 @@ bool ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager, } } -#if 0 - // jingham: look here - StreamFile logfile ("/tmp/exprs.txt", "a"); - logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n", - m_jit_start_addr, - m_function_name.c_str(), - m_function_text.c_str()); -#endif - DeclMap()->DidParse(); ResetDeclMap(); diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp index d0ef688f07735..262a7914d249d 100644 --- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -12,12 +12,12 @@ #include "EmulateInstructionARM.h" #include "EmulationStateARM.h" #include "lldb/Core/Address.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Host/PosixApi.h" #include "lldb/Interpreter/OptionValueArray.h" #include "lldb/Interpreter/OptionValueDictionary.h" #include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Stream.h" diff --git a/source/Plugins/Instruction/ARM/EmulationStateARM.cpp b/source/Plugins/Instruction/ARM/EmulationStateARM.cpp index 5e90965c18812..d1032f56f31cf 100644 --- a/source/Plugins/Instruction/ARM/EmulationStateARM.cpp +++ b/source/Plugins/Instruction/ARM/EmulationStateARM.cpp @@ -203,7 +203,8 @@ size_t EmulationStateARM::WritePseudoMemory( uint32_t value1; uint32_t value2; memcpy (&value1, dst, sizeof (uint32_t)); - memcpy (&value2, (uint8_t *) dst + sizeof (uint32_t), sizeof (uint32_t)); + memcpy(&value2, static_cast<const uint8_t *>(dst) + sizeof(uint32_t), + sizeof(uint32_t)); if (endian::InlHostByteOrder() == lldb::eByteOrderBig) { value1 = llvm::ByteSwap_32(value1); value2 = llvm::ByteSwap_32(value2); diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp index 54dd237eb4b73..d882108c25f41 100644 --- a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp +++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp @@ -12,10 +12,10 @@ #include <stdlib.h> #include "lldb/Core/Address.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Stream.h" @@ -167,10 +167,7 @@ EmulateInstructionARM64::CreateInstance(const ArchSpec &arch, if (EmulateInstructionARM64::SupportsEmulatingInstructionsOfTypeStatic( inst_type)) { if (arch.GetTriple().getArch() == llvm::Triple::aarch64) { - std::auto_ptr<EmulateInstructionARM64> emulate_insn_ap( - new EmulateInstructionARM64(arch)); - if (emulate_insn_ap.get()) - return emulate_insn_ap.release(); + return new EmulateInstructionARM64(arch); } } diff --git a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp index 4d1d89abb1d0f..db3d8fc1b8ca2 100644 --- a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp +++ b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp @@ -12,12 +12,12 @@ #include <stdlib.h> #include "lldb/Core/Address.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Opcode.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Stream.h" @@ -212,10 +212,7 @@ EmulateInstructionMIPS::CreateInstance(const ArchSpec &arch, inst_type)) { if (arch.GetTriple().getArch() == llvm::Triple::mips || arch.GetTriple().getArch() == llvm::Triple::mipsel) { - std::auto_ptr<EmulateInstructionMIPS> emulate_insn_ap( - new EmulateInstructionMIPS(arch)); - if (emulate_insn_ap.get()) - return emulate_insn_ap.release(); + return new EmulateInstructionMIPS(arch); } } diff --git a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp index 1e6d98756958b..d298589afdd9e 100644 --- a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp +++ b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp @@ -12,12 +12,12 @@ #include <stdlib.h> #include "lldb/Core/Address.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Opcode.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Host/PosixApi.h" #include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Stream.h" @@ -199,10 +199,7 @@ EmulateInstructionMIPS64::CreateInstance(const ArchSpec &arch, inst_type)) { if (arch.GetTriple().getArch() == llvm::Triple::mips64 || arch.GetTriple().getArch() == llvm::Triple::mips64el) { - std::auto_ptr<EmulateInstructionMIPS64> emulate_insn_ap( - new EmulateInstructionMIPS64(arch)); - if (emulate_insn_ap.get()) - return emulate_insn_ap.release(); + return new EmulateInstructionMIPS64(arch); } } @@ -801,7 +798,9 @@ EmulateInstructionMIPS64::GetOpcodeForInstruction(const char *op_name) { // Branch instructions //---------------------------------------------------------------------- {"BEQ", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"}, + {"BEQ64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"}, {"BNE", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"}, + {"BNE64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"}, {"BEQL", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQL rs,rt,offset"}, {"BNEL", &EmulateInstructionMIPS64::Emulate_BXX_3ops, @@ -814,6 +813,7 @@ EmulateInstructionMIPS64::GetOpcodeForInstruction(const char *op_name) { {"BALC", &EmulateInstructionMIPS64::Emulate_BALC, "BALC offset"}, {"BC", &EmulateInstructionMIPS64::Emulate_BC, "BC offset"}, {"BGEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"}, + {"BGEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"}, {"BLEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C, "BLEZALC rs,offset"}, {"BGEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C, @@ -828,34 +828,61 @@ EmulateInstructionMIPS64::GetOpcodeForInstruction(const char *op_name) { "BNEZALC rs,offset"}, {"BEQC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BEQC rs,rt,offset"}, + {"BEQC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, + "BEQC rs,rt,offset"}, {"BNEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BNEC rs,rt,offset"}, + {"BNEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, + "BNEC rs,rt,offset"}, {"BLTC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BLTC rs,rt,offset"}, + {"BLTC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, + "BLTC rs,rt,offset"}, {"BGEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BGEC rs,rt,offset"}, + {"BGEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, + "BGEC rs,rt,offset"}, {"BLTUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BLTUC rs,rt,offset"}, + {"BLTUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, + "BLTUC rs,rt,offset"}, {"BGEUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BGEUC rs,rt,offset"}, + {"BGEUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, + "BGEUC rs,rt,offset"}, {"BLTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BLTZC rt,offset"}, + {"BLTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, + "BLTZC rt,offset"}, {"BLEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BLEZC rt,offset"}, + {"BLEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, + "BLEZC rt,offset"}, {"BGEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BGEZC rt,offset"}, + {"BGEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, + "BGEZC rt,offset"}, {"BGTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BGTZC rt,offset"}, + {"BGTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, + "BGTZC rt,offset"}, {"BEQZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BEQZC rt,offset"}, + {"BEQZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, + "BEQZC rt,offset"}, {"BNEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BNEZC rt,offset"}, + {"BNEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, + "BNEZC rt,offset"}, {"BGEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZL rt,offset"}, {"BGTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"}, + {"BGTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"}, {"BGTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZL rt,offset"}, {"BLEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"}, + {"BLEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"}, {"BLEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZL rt,offset"}, {"BLTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"}, + {"BLTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"}, {"BLTZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BLTZAL rt,offset"}, {"BLTZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, @@ -872,8 +899,11 @@ EmulateInstructionMIPS64::GetOpcodeForInstruction(const char *op_name) { {"JALR64", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"}, {"JALR_HB", &EmulateInstructionMIPS64::Emulate_JALR, "JALR.HB target"}, {"JIALC", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"}, + {"JIALC64", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"}, {"JIC", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"}, + {"JIC64", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"}, {"JR", &EmulateInstructionMIPS64::Emulate_JR, "JR target"}, + {"JR64", &EmulateInstructionMIPS64::Emulate_JR, "JR target"}, {"JR_HB", &EmulateInstructionMIPS64::Emulate_JR, "JR.HB target"}, {"BC1F", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1F cc, offset"}, {"BC1T", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1T cc, offset"}, @@ -1338,12 +1368,14 @@ bool EmulateInstructionMIPS64::Emulate_BXX_3ops(llvm::MCInst &insn) { if (!success) return false; - if (!strcasecmp(op_name, "BEQ") || !strcasecmp(op_name, "BEQL")) { + if (!strcasecmp(op_name, "BEQ") || !strcasecmp(op_name, "BEQL") + || !strcasecmp(op_name, "BEQ64") ) { if (rs_val == rt_val) target = pc + offset; else target = pc + 8; - } else if (!strcasecmp(op_name, "BNE") || !strcasecmp(op_name, "BNEL")) { + } else if (!strcasecmp(op_name, "BNE") || !strcasecmp(op_name, "BNEL") + || !strcasecmp(op_name, "BNE64")) { if (rs_val != rt_val) target = pc + offset; else @@ -1563,22 +1595,26 @@ bool EmulateInstructionMIPS64::Emulate_BXX_2ops(llvm::MCInst &insn) { if (!success) return false; - if (!strcasecmp(op_name, "BLTZL") || !strcasecmp(op_name, "BLTZ")) { + if (!strcasecmp(op_name, "BLTZL") || !strcasecmp(op_name, "BLTZ") + || !strcasecmp(op_name, "BLTZ64")) { if (rs_val < 0) target = pc + offset; else target = pc + 8; - } else if (!strcasecmp(op_name, "BGEZL") || !strcasecmp(op_name, "BGEZ")) { + } else if (!strcasecmp(op_name, "BGEZL") || !strcasecmp(op_name, "BGEZ") + || !strcasecmp(op_name, "BGEZ64")) { if (rs_val >= 0) target = pc + offset; else target = pc + 8; - } else if (!strcasecmp(op_name, "BGTZL") || !strcasecmp(op_name, "BGTZ")) { + } else if (!strcasecmp(op_name, "BGTZL") || !strcasecmp(op_name, "BGTZ") + || !strcasecmp(op_name, "BGTZ64")) { if (rs_val > 0) target = pc + offset; else target = pc + 8; - } else if (!strcasecmp(op_name, "BLEZL") || !strcasecmp(op_name, "BLEZ")) { + } else if (!strcasecmp(op_name, "BLEZL") || !strcasecmp(op_name, "BLEZ") + || !strcasecmp(op_name, "BLEZ64")) { if (rs_val <= 0) target = pc + offset; else @@ -1657,32 +1693,32 @@ bool EmulateInstructionMIPS64::Emulate_BXX_3ops_C(llvm::MCInst &insn) { if (!success) return false; - if (!strcasecmp(op_name, "BEQC")) { + if (!strcasecmp(op_name, "BEQC") || !strcasecmp(op_name, "BEQC64")) { if (rs_val == rt_val) target = pc + offset; else target = pc + 4; - } else if (!strcasecmp(op_name, "BNEC")) { + } else if (!strcasecmp(op_name, "BNEC") || !strcasecmp(op_name, "BNEC64")) { if (rs_val != rt_val) target = pc + offset; else target = pc + 4; - } else if (!strcasecmp(op_name, "BLTC")) { + } else if (!strcasecmp(op_name, "BLTC") || !strcasecmp(op_name, "BLTC64")) { if (rs_val < rt_val) target = pc + offset; else target = pc + 4; - } else if (!strcasecmp(op_name, "BGEC")) { + } else if (!strcasecmp(op_name, "BGEC64") || !strcasecmp(op_name, "BGEC")) { if (rs_val >= rt_val) target = pc + offset; else target = pc + 4; - } else if (!strcasecmp(op_name, "BLTUC")) { + } else if (!strcasecmp(op_name, "BLTUC") || !strcasecmp(op_name, "BLTUC64")) { if (rs_val < rt_val) target = pc + offset; else target = pc + 4; - } else if (!strcasecmp(op_name, "BGEUC")) { + } else if (!strcasecmp(op_name, "BGEUC") || !strcasecmp(op_name, "BGEUC64")) { if ((uint32_t)rs_val >= (uint32_t)rt_val) target = pc + offset; else @@ -1734,32 +1770,32 @@ bool EmulateInstructionMIPS64::Emulate_BXX_2ops_C(llvm::MCInst &insn) { if (!success) return false; - if (!strcasecmp(op_name, "BLTZC")) { + if (!strcasecmp(op_name, "BLTZC") || !strcasecmp(op_name, "BLTZC64")) { if (rs_val < 0) target = pc + offset; else target = pc + 4; - } else if (!strcasecmp(op_name, "BLEZC")) { + } else if (!strcasecmp(op_name, "BLEZC") || !strcasecmp(op_name, "BLEZC64")) { if (rs_val <= 0) target = pc + offset; else target = pc + 4; - } else if (!strcasecmp(op_name, "BGEZC")) { + } else if (!strcasecmp(op_name, "BGEZC") || !strcasecmp(op_name, "BGEZC64")) { if (rs_val >= 0) target = pc + offset; else target = pc + 4; - } else if (!strcasecmp(op_name, "BGTZC")) { + } else if (!strcasecmp(op_name, "BGTZC") || !strcasecmp(op_name, "BGTZC64")) { if (rs_val > 0) target = pc + offset; else target = pc + 4; - } else if (!strcasecmp(op_name, "BEQZC")) { + } else if (!strcasecmp(op_name, "BEQZC") || !strcasecmp(op_name, "BEQZC64")) { if (rs_val == 0) target = pc + offset; else target = pc + 4; - } else if (!strcasecmp(op_name, "BNEZC")) { + } else if (!strcasecmp(op_name, "BNEZC") || !strcasecmp(op_name, "BNEZC64")) { if (rs_val != 0) target = pc + offset; else diff --git a/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/source/Plugins/Language/CPlusPlus/CMakeLists.txt index 8f769c499987f..180440a244a4a 100644 --- a/source/Plugins/Language/CPlusPlus/CMakeLists.txt +++ b/source/Plugins/Language/CPlusPlus/CMakeLists.txt @@ -5,9 +5,12 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN CxxStringTypes.cpp LibCxx.cpp LibCxxAtomic.cpp + LibCxxBitset.cpp LibCxxInitializerList.cpp LibCxxList.cpp LibCxxMap.cpp + LibCxxQueue.cpp + LibCxxTuple.cpp LibCxxUnorderedMap.cpp LibCxxVector.cpp LibStdcpp.cpp diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 1ae9418e4d9c0..51ed88065c84d 100644 --- a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -422,12 +422,24 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { AddCXXSynthetic( cpp_category_sp, + lldb_private::formatters::LibcxxBitsetSyntheticFrontEndCreator, + "libc++ std::bitset synthetic children", + ConstString("^std::__(ndk)?1::bitset<.+>(( )?&)?$"), stl_synth_flags, + true); + AddCXXSynthetic( + cpp_category_sp, lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator, "libc++ std::vector synthetic children", ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"), stl_synth_flags, true); AddCXXSynthetic( cpp_category_sp, + lldb_private::formatters::LibcxxStdForwardListSyntheticFrontEndCreator, + "libc++ std::forward_list synthetic children", + ConstString("^std::__(ndk)?1::forward_list<.+>(( )?&)?$"), + stl_synth_flags, true); + AddCXXSynthetic( + cpp_category_sp, lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator, "libc++ std::list synthetic children", ConstString("^std::__(ndk)?1::list<.+>(( )?&)?$"), stl_synth_flags, true); @@ -467,6 +479,14 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "libc++ std::initializer_list synthetic children", ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags, true); + AddCXXSynthetic(cpp_category_sp, LibcxxQueueFrontEndCreator, + "libc++ std::queue synthetic children", + ConstString("^std::__(ndk)?1::queue<.+>(( )?&)?$"), + stl_synth_flags, true); + AddCXXSynthetic(cpp_category_sp, LibcxxTupleFrontEndCreator, + "libc++ std::tuple synthetic children", + ConstString("^std::__(ndk)?1::tuple<.*>(( )?&)?$"), stl_synth_flags, + true); AddCXXSynthetic( cpp_category_sp, lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator, @@ -497,12 +517,22 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { stl_summary_flags.SetSkipPointers(false); AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, + "libc++ std::bitset summary provider", + ConstString("^std::__(ndk)?1::bitset<.+>(( )?&)?$"), + stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector summary provider", ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"), stl_summary_flags, true); AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::list summary provider", + ConstString("^std::__(ndk)?1::forward_list<.+>(( )?&)?$"), + stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxContainerSummaryProvider, + "libc++ std::list summary provider", ConstString("^std::__(ndk)?1::list<.+>(( )?&)?$"), stl_summary_flags, true); AddCXXSummary(cpp_category_sp, @@ -517,6 +547,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { stl_summary_flags, true); AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, + "libc++ std::queue summary provider", + ConstString("^std::__(ndk)?1::queue<.+>(( )?&)?$"), + stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::set summary provider", ConstString("^std::__(ndk)?1::set<.+>(( )?&)?$"), stl_summary_flags, true); @@ -535,6 +570,10 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "libc++ std::unordered containers summary provider", ConstString("^(std::__(ndk)?1::)unordered_(multi)?(map|set)<.+> >$"), stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, LibcxxContainerSummaryProvider, + "libc++ std::tuple summary provider", + ConstString("^std::__(ndk)?1::tuple<.*>(( )?&)?$"), stl_summary_flags, + true); AddCXXSummary( cpp_category_sp, lldb_private::formatters::LibCxxAtomicSummaryProvider, "libc++ std::atomic summary provider", diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp b/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp index 88bdd68ff3011..aebea6ae3569b 100644 --- a/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp +++ b/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp @@ -628,7 +628,7 @@ static const clang::LangOptions &GetLangOptions() { g_options.CPlusPlus = true; g_options.CPlusPlus11 = true; g_options.CPlusPlus14 = true; - g_options.CPlusPlus1z = true; + g_options.CPlusPlus17 = true; }); return g_options; } diff --git a/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/source/Plugins/Language/CPlusPlus/LibCxx.cpp index 11245e1310b77..f6d1f18cb596b 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxx.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxx.cpp @@ -153,12 +153,11 @@ bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() { .get(); if (m_pair_ptr) { auto __i_(valobj_sp->GetChildMemberWithName(g___i_, true)); - lldb::TemplateArgumentKind kind; if (!__i_) { m_pair_ptr = nullptr; return false; } - CompilerType pair_type(__i_->GetCompilerType().GetTemplateArgument(0, kind)); + CompilerType pair_type(__i_->GetCompilerType().GetTypeTemplateArgument(0)); std::string name; uint64_t bit_offset_ptr; uint32_t bitfield_bit_size_ptr; bool is_bitfield_ptr; pair_type = pair_type.GetFieldAtIndex(0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr); if (!pair_type) { diff --git a/source/Plugins/Language/CPlusPlus/LibCxx.h b/source/Plugins/Language/CPlusPlus/LibCxx.h index 7610212b4245a..3f6e0d6e14d7f 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxx.h +++ b/source/Plugins/Language/CPlusPlus/LibCxx.h @@ -93,6 +93,10 @@ private: }; SyntheticChildrenFrontEnd * +LibcxxBitsetSyntheticFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP); + +SyntheticChildrenFrontEnd * LibcxxSharedPtrSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); @@ -105,6 +109,10 @@ LibcxxStdListSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); SyntheticChildrenFrontEnd * +LibcxxStdForwardListSyntheticFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP); + +SyntheticChildrenFrontEnd * LibcxxStdMapSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); @@ -119,6 +127,12 @@ LibcxxInitializerListSyntheticFrontEndCreator(CXXSyntheticChildren *, SyntheticChildrenFrontEnd *LibcxxFunctionFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); +SyntheticChildrenFrontEnd *LibcxxQueueFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP); + +SyntheticChildrenFrontEnd *LibcxxTupleFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP); + } // namespace formatters } // namespace lldb_private diff --git a/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp b/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp new file mode 100644 index 0000000000000..0cdb0b26cf3bd --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp @@ -0,0 +1,107 @@ +//===-- LibCxxBitset.cpp ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "LibCxx.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; + +namespace { + +class BitsetFrontEnd : public SyntheticChildrenFrontEnd { +public: + BitsetFrontEnd(ValueObject &valobj); + + size_t GetIndexOfChildWithName(const ConstString &name) override { + return formatters::ExtractIndexFromString(name.GetCString()); + } + + bool MightHaveChildren() override { return true; } + bool Update() override; + size_t CalculateNumChildren() override { return m_elements.size(); } + ValueObjectSP GetChildAtIndex(size_t idx) override; + +private: + std::vector<ValueObjectSP> m_elements; + ValueObjectSP m_first; + CompilerType m_bool_type; + ByteOrder m_byte_order = eByteOrderInvalid; + uint8_t m_byte_size = 0; +}; +} // namespace + +BitsetFrontEnd::BitsetFrontEnd(ValueObject &valobj) + : SyntheticChildrenFrontEnd(valobj) { + m_bool_type = valobj.GetCompilerType().GetBasicTypeFromAST(eBasicTypeBool); + if (auto target_sp = m_backend.GetTargetSP()) { + m_byte_order = target_sp->GetArchitecture().GetByteOrder(); + m_byte_size = target_sp->GetArchitecture().GetAddressByteSize(); + Update(); + } +} + +bool BitsetFrontEnd::Update() { + m_elements.clear(); + m_first.reset(); + + TargetSP target_sp = m_backend.GetTargetSP(); + if (!target_sp) + return false; + size_t capping_size = target_sp->GetMaximumNumberOfChildrenToDisplay(); + + size_t size = 0; + if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(0)) + size = arg->value.getLimitedValue(capping_size); + + m_elements.assign(size, ValueObjectSP()); + + m_first = m_backend.GetChildMemberWithName(ConstString("__first_"), true); + return false; +} + +ValueObjectSP BitsetFrontEnd::GetChildAtIndex(size_t idx) { + if (idx >= m_elements.size() || !m_first) + return ValueObjectSP(); + + if (m_elements[idx]) + return m_elements[idx]; + + ExecutionContext ctx = m_backend.GetExecutionContextRef().Lock(false); + CompilerType type; + ValueObjectSP chunk; + // For small bitsets __first_ is not an array, but a plain size_t. + if (m_first->GetCompilerType().IsArrayType(&type, nullptr, nullptr)) + chunk = m_first->GetChildAtIndex( + idx / type.GetBitSize(ctx.GetBestExecutionContextScope()), true); + else { + type = m_first->GetCompilerType(); + chunk = m_first; + } + if (!type || !chunk) + return ValueObjectSP(); + + size_t chunk_idx = idx % type.GetBitSize(ctx.GetBestExecutionContextScope()); + uint8_t value = !!(chunk->GetValueAsUnsigned(0) & (uint64_t(1) << chunk_idx)); + DataExtractor data(&value, sizeof(value), m_byte_order, m_byte_size); + + m_elements[idx] = CreateValueObjectFromData(llvm::formatv("[{0}]", idx).str(), + data, ctx, m_bool_type); + + return m_elements[idx]; +} + +SyntheticChildrenFrontEnd *formatters::LibcxxBitsetSyntheticFrontEndCreator( + CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { + if (valobj_sp) + return new BitsetFrontEnd(*valobj_sp); + return nullptr; +} diff --git a/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp b/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp index 4e839532afb79..5823f6f3e0382 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp @@ -94,9 +94,8 @@ bool lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd:: m_start = nullptr; m_num_elements = 0; - lldb::TemplateArgumentKind kind; - m_element_type = m_backend.GetCompilerType().GetTemplateArgument(0, kind); - if (kind != lldb::eTemplateArgumentKindType || !m_element_type.IsValid()) + m_element_type = m_backend.GetCompilerType().GetTypeTemplateArgument(0); + if (!m_element_type.IsValid()) return false; m_element_size = m_element_type.GetByteSize(nullptr); diff --git a/source/Plugins/Language/CPlusPlus/LibCxxList.cpp b/source/Plugins/Language/CPlusPlus/LibCxxList.cpp index 56d8edaba72ac..6407ae129ad7d 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxList.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxList.cpp @@ -114,58 +114,90 @@ private: ListEntry m_entry; }; -} // end anonymous namespace - -namespace lldb_private { -namespace formatters { -class LibcxxStdListSyntheticFrontEnd : public SyntheticChildrenFrontEnd { +class AbstractListFrontEnd : public SyntheticChildrenFrontEnd { public: - LibcxxStdListSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + size_t GetIndexOfChildWithName(const ConstString &name) override { + return ExtractIndexFromString(name.GetCString()); + } + bool MightHaveChildren() override { return true; } + bool Update() override; - ~LibcxxStdListSyntheticFrontEnd() override = default; +protected: + AbstractListFrontEnd(ValueObject &valobj) + : SyntheticChildrenFrontEnd(valobj) {} - size_t CalculateNumChildren() override; + size_t m_count; + ValueObject *m_head; - lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; + static constexpr bool g_use_loop_detect = true; + size_t m_loop_detected; // The number of elements that have had loop detection + // run over them. + ListEntry m_slow_runner; // Used for loop detection + ListEntry m_fast_runner; // Used for loop detection + + size_t m_list_capping_size; + CompilerType m_element_type; + std::map<size_t, ListIterator> m_iterators; + + bool HasLoop(size_t count); + ValueObjectSP GetItem(size_t idx); +}; +class ForwardListFrontEnd : public AbstractListFrontEnd { +public: + ForwardListFrontEnd(ValueObject &valobj); + + size_t CalculateNumChildren() override; + ValueObjectSP GetChildAtIndex(size_t idx) override; bool Update() override; +}; - bool MightHaveChildren() override; +class ListFrontEnd : public AbstractListFrontEnd { +public: + ListFrontEnd(lldb::ValueObjectSP valobj_sp); - size_t GetIndexOfChildWithName(const ConstString &name) override; + ~ListFrontEnd() override = default; -private: - bool HasLoop(size_t count); + size_t CalculateNumChildren() override; - size_t m_list_capping_size; - static const bool g_use_loop_detect = true; + lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; - size_t m_loop_detected; // The number of elements that have had loop detection - // run over them. - ListEntry m_slow_runner; // Used for loop detection - ListEntry m_fast_runner; // Used for loop detection + bool Update() override; +private: lldb::addr_t m_node_address; - ValueObject *m_head; ValueObject *m_tail; - CompilerType m_element_type; - size_t m_count; - std::map<size_t, ListIterator> m_iterators; }; -} // namespace formatters -} // namespace lldb_private - -lldb_private::formatters::LibcxxStdListSyntheticFrontEnd:: - LibcxxStdListSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) - : SyntheticChildrenFrontEnd(*valobj_sp), m_list_capping_size(0), - m_loop_detected(0), m_node_address(), m_head(nullptr), m_tail(nullptr), - m_element_type(), m_count(UINT32_MAX), m_iterators() { - if (valobj_sp) - Update(); + +} // end anonymous namespace + +bool AbstractListFrontEnd::Update() { + m_loop_detected = 0; + m_count = UINT32_MAX; + m_head = nullptr; + m_list_capping_size = 0; + m_slow_runner.SetEntry(nullptr); + m_fast_runner.SetEntry(nullptr); + m_iterators.clear(); + + if (m_backend.GetTargetSP()) + m_list_capping_size = + m_backend.GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); + if (m_list_capping_size == 0) + m_list_capping_size = 255; + + CompilerType list_type = m_backend.GetCompilerType(); + if (list_type.IsReferenceType()) + list_type = list_type.GetNonReferenceType(); + + if (list_type.GetNumTemplateArguments() == 0) + return false; + m_element_type = list_type.GetTypeTemplateArgument(0); + + return false; } -bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop( - size_t count) { +bool AbstractListFrontEnd::HasLoop(size_t count) { if (!g_use_loop_detect) return false; // don't bother checking for a loop if we won't actually need to jump nodes @@ -201,8 +233,105 @@ bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop( return m_slow_runner == m_fast_runner; } -size_t lldb_private::formatters::LibcxxStdListSyntheticFrontEnd:: - CalculateNumChildren() { +ValueObjectSP AbstractListFrontEnd::GetItem(size_t idx) { + size_t advance = idx; + ListIterator current(m_head); + if (idx > 0) { + auto cached_iterator = m_iterators.find(idx - 1); + if (cached_iterator != m_iterators.end()) { + current = cached_iterator->second; + advance = 1; + } + } + ValueObjectSP value_sp = current.advance(advance); + m_iterators[idx] = current; + return value_sp; +} + +ForwardListFrontEnd::ForwardListFrontEnd(ValueObject &valobj) + : AbstractListFrontEnd(valobj) { + Update(); +} + +size_t ForwardListFrontEnd::CalculateNumChildren() { + if (m_count != UINT32_MAX) + return m_count; + + ListEntry current(m_head); + m_count = 0; + while (current && m_count < m_list_capping_size) { + ++m_count; + current = current.next(); + } + return m_count; +} + +ValueObjectSP ForwardListFrontEnd::GetChildAtIndex(size_t idx) { + if (idx >= CalculateNumChildren()) + return nullptr; + + if (!m_head) + return nullptr; + + if (HasLoop(idx + 1)) + return nullptr; + + ValueObjectSP current_sp = GetItem(idx); + if (!current_sp) + return nullptr; + + current_sp = current_sp->GetChildAtIndex(1, true); // get the __value_ child + if (!current_sp) + return nullptr; + + // we need to copy current_sp into a new object otherwise we will end up with + // all items named __value_ + DataExtractor data; + Status error; + current_sp->GetData(data, error); + if (error.Fail()) + return nullptr; + + return CreateValueObjectFromData(llvm::formatv("[{0}]", idx).str(), data, + m_backend.GetExecutionContextRef(), + m_element_type); +} + +static ValueObjectSP GetValueOfCompressedPair(ValueObject &pair) { + ValueObjectSP value = pair.GetChildMemberWithName(ConstString("__value_"), true); + if (! value) { + // pre-r300140 member name + value = pair.GetChildMemberWithName(ConstString("__first_"), true); + } + return value; +} + +bool ForwardListFrontEnd::Update() { + AbstractListFrontEnd::Update(); + + Status err; + ValueObjectSP backend_addr(m_backend.AddressOf(err)); + if (err.Fail() || !backend_addr) + return false; + + ValueObjectSP impl_sp( + m_backend.GetChildMemberWithName(ConstString("__before_begin_"), true)); + if (!impl_sp) + return false; + impl_sp = GetValueOfCompressedPair(*impl_sp); + if (!impl_sp) + return false; + m_head = impl_sp->GetChildMemberWithName(ConstString("__next_"), true).get(); + return false; +} + +ListFrontEnd::ListFrontEnd(lldb::ValueObjectSP valobj_sp) + : AbstractListFrontEnd(*valobj_sp), m_node_address(), m_tail(nullptr) { + if (valobj_sp) + Update(); +} + +size_t ListFrontEnd::CalculateNumChildren() { if (m_count != UINT32_MAX) return m_count; if (!m_head || !m_tail || m_node_address == 0) @@ -210,10 +339,9 @@ size_t lldb_private::formatters::LibcxxStdListSyntheticFrontEnd:: ValueObjectSP size_alloc( m_backend.GetChildMemberWithName(ConstString("__size_alloc_"), true)); if (size_alloc) { - ValueObjectSP first( - size_alloc->GetChildMemberWithName(ConstString("__first_"), true)); - if (first) { - m_count = first->GetValueAsUnsigned(UINT32_MAX); + ValueObjectSP value = GetValueOfCompressedPair(*size_alloc); + if (value) { + m_count = value->GetValueAsUnsigned(UINT32_MAX); } } if (m_count != UINT32_MAX) { @@ -239,9 +367,7 @@ size_t lldb_private::formatters::LibcxxStdListSyntheticFrontEnd:: } } -lldb::ValueObjectSP -lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex( - size_t idx) { +lldb::ValueObjectSP ListFrontEnd::GetChildAtIndex(size_t idx) { static ConstString g_value("__value_"); static ConstString g_next("__next_"); @@ -254,23 +380,10 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex( if (HasLoop(idx + 1)) return lldb::ValueObjectSP(); - size_t actual_advance = idx; - - ListIterator current(m_head); - if (idx > 0) { - auto cached_iterator = m_iterators.find(idx - 1); - if (cached_iterator != m_iterators.end()) { - current = cached_iterator->second; - actual_advance = 1; - } - } - - ValueObjectSP current_sp(current.advance(actual_advance)); + ValueObjectSP current_sp = GetItem(idx); if (!current_sp) return lldb::ValueObjectSP(); - m_iterators[idx] = current; - current_sp = current_sp->GetChildAtIndex(1, true); // get the __value_ child if (!current_sp) return lldb::ValueObjectSP(); @@ -303,23 +416,13 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex( m_element_type); } -bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::Update() { - m_iterators.clear(); - m_head = m_tail = nullptr; +bool ListFrontEnd::Update() { + AbstractListFrontEnd::Update(); + m_tail = nullptr; m_node_address = 0; - m_count = UINT32_MAX; - m_loop_detected = 0; - m_slow_runner.SetEntry(nullptr); - m_fast_runner.SetEntry(nullptr); Status err; ValueObjectSP backend_addr(m_backend.AddressOf(err)); - m_list_capping_size = 0; - if (m_backend.GetTargetSP()) - m_list_capping_size = - m_backend.GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); - if (m_list_capping_size == 0) - m_list_capping_size = 255; if (err.Fail() || !backend_addr) return false; m_node_address = backend_addr->GetValueAsUnsigned(0); @@ -329,31 +432,18 @@ bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::Update() { m_backend.GetChildMemberWithName(ConstString("__end_"), true)); if (!impl_sp) return false; - CompilerType list_type = m_backend.GetCompilerType(); - if (list_type.IsReferenceType()) - list_type = list_type.GetNonReferenceType(); - - if (list_type.GetNumTemplateArguments() == 0) - return false; - lldb::TemplateArgumentKind kind; - m_element_type = list_type.GetTemplateArgument(0, kind); m_head = impl_sp->GetChildMemberWithName(ConstString("__next_"), true).get(); m_tail = impl_sp->GetChildMemberWithName(ConstString("__prev_"), true).get(); return false; } -bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd:: - MightHaveChildren() { - return true; -} - -size_t lldb_private::formatters::LibcxxStdListSyntheticFrontEnd:: - GetIndexOfChildWithName(const ConstString &name) { - return ExtractIndexFromString(name.GetCString()); +SyntheticChildrenFrontEnd *formatters::LibcxxStdListSyntheticFrontEndCreator( + CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { + return (valobj_sp ? new ListFrontEnd(valobj_sp) : nullptr); } SyntheticChildrenFrontEnd * -lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator( +formatters::LibcxxStdForwardListSyntheticFrontEndCreator( CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { - return (valobj_sp ? new LibcxxStdListSyntheticFrontEnd(valobj_sp) : nullptr); + return valobj_sp ? new ForwardListFrontEnd(*valobj_sp) : nullptr; } diff --git a/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp index b7215dbcbb485..be96a6d95bcd5 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp @@ -268,13 +268,12 @@ bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType() { m_element_type = deref->GetCompilerType(); return true; } - lldb::TemplateArgumentKind kind; deref = m_backend.GetChildAtNamePath({g_tree_, g_pair3}); if (!deref) return false; - m_element_type = - deref->GetCompilerType().GetTemplateArgument(1, kind).GetTemplateArgument( - 1, kind); + m_element_type = deref->GetCompilerType() + .GetTypeTemplateArgument(1) + .GetTypeTemplateArgument(1); if (m_element_type) { std::string name; uint64_t bit_offset_ptr; @@ -285,7 +284,7 @@ bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType() { m_element_type = m_element_type.GetTypedefedType(); return m_element_type.IsValid(); } else { - m_element_type = m_backend.GetCompilerType().GetTemplateArgument(0, kind); + m_element_type = m_backend.GetCompilerType().GetTypeTemplateArgument(0); return m_element_type.IsValid(); } } diff --git a/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp b/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp new file mode 100644 index 0000000000000..c4e0b66d4272e --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp @@ -0,0 +1,61 @@ +//===-- LibCxxQueue.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "LibCxx.h" +#include "lldb/DataFormatters/FormattersHelpers.h" + +using namespace lldb; +using namespace lldb_private; + +namespace { + +class QueueFrontEnd : public SyntheticChildrenFrontEnd { +public: + QueueFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) { + Update(); + } + + size_t GetIndexOfChildWithName(const ConstString &name) override { + return m_container_sp ? m_container_sp->GetIndexOfChildWithName(name) + : UINT32_MAX; + } + + bool MightHaveChildren() override { return true; } + bool Update() override; + + size_t CalculateNumChildren() override { + return m_container_sp ? m_container_sp->GetNumChildren() : 0; + } + + ValueObjectSP GetChildAtIndex(size_t idx) override { + return m_container_sp ? m_container_sp->GetChildAtIndex(idx, true) + : nullptr; + } + +private: + ValueObjectSP m_container_sp; +}; +} // namespace + +bool QueueFrontEnd::Update() { + m_container_sp.reset(); + ValueObjectSP c_sp = m_backend.GetChildMemberWithName(ConstString("c"), true); + if (!c_sp) + return false; + m_container_sp = c_sp->GetSyntheticValue(); + return false; +} + +SyntheticChildrenFrontEnd * +formatters::LibcxxQueueFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP valobj_sp) { + if (valobj_sp) + return new QueueFrontEnd(*valobj_sp); + return nullptr; +} diff --git a/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp b/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp new file mode 100644 index 0000000000000..9b412a12f532f --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp @@ -0,0 +1,83 @@ +//===-- LibCxxTuple.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "LibCxx.h" +#include "lldb/DataFormatters/FormattersHelpers.h" + +using namespace lldb; +using namespace lldb_private; + +namespace { + +class TupleFrontEnd: public SyntheticChildrenFrontEnd { +public: + TupleFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) { + Update(); + } + + size_t GetIndexOfChildWithName(const ConstString &name) override { + return formatters::ExtractIndexFromString(name.GetCString()); + } + + bool MightHaveChildren() override { return true; } + bool Update() override; + size_t CalculateNumChildren() override { return m_elements.size(); } + ValueObjectSP GetChildAtIndex(size_t idx) override; + +private: + std::vector<ValueObjectSP> m_elements; + ValueObjectSP m_base_sp; +}; +} + +bool TupleFrontEnd::Update() { + m_elements.clear(); + m_base_sp = m_backend.GetChildMemberWithName(ConstString("__base_"), true); + if (! m_base_sp) { + // Pre r304382 name of the base element. + m_base_sp = m_backend.GetChildMemberWithName(ConstString("base_"), true); + } + if (! m_base_sp) + return false; + m_elements.assign(m_base_sp->GetCompilerType().GetNumDirectBaseClasses(), + ValueObjectSP()); + return false; +} + +ValueObjectSP TupleFrontEnd::GetChildAtIndex(size_t idx) { + if (idx >= m_elements.size()) + return ValueObjectSP(); + if (!m_base_sp) + return ValueObjectSP(); + if (m_elements[idx]) + return m_elements[idx]; + + CompilerType holder_type = + m_base_sp->GetCompilerType().GetDirectBaseClassAtIndex(idx, nullptr); + if (!holder_type) + return ValueObjectSP(); + ValueObjectSP holder_sp = m_base_sp->GetChildAtIndex(idx, true); + if (!holder_sp) + return ValueObjectSP(); + + ValueObjectSP elem_sp = holder_sp->GetChildAtIndex(0, true); + if (elem_sp) + m_elements[idx] = + elem_sp->Clone(ConstString(llvm::formatv("[{0}]", idx).str())); + + return m_elements[idx]; +} + +SyntheticChildrenFrontEnd * +formatters::LibcxxTupleFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP valobj_sp) { + if (valobj_sp) + return new TupleFrontEnd(*valobj_sp); + return nullptr; +} diff --git a/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp b/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp index 190b5f64381ea..0f1c2537d651e 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp @@ -121,11 +121,10 @@ lldb::ValueObjectSP lldb_private::formatters:: if (!first_sp) return nullptr; m_element_type = first_sp->GetCompilerType(); - lldb::TemplateArgumentKind kind; - m_element_type = m_element_type.GetTemplateArgument(0, kind); + m_element_type = m_element_type.GetTypeTemplateArgument(0); m_element_type = m_element_type.GetPointeeType(); m_node_type = m_element_type; - m_element_type = m_element_type.GetTemplateArgument(0, kind); + m_element_type = m_element_type.GetTypeTemplateArgument(0); std::string name; m_element_type = m_element_type.GetFieldAtIndex(0, name, nullptr, nullptr, nullptr); diff --git a/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp b/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp index 6f601c9f6ccbf..711130639cd2f 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp @@ -290,8 +290,7 @@ lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator( CompilerType type = valobj_sp->GetCompilerType(); if (!type.IsValid() || type.GetNumTemplateArguments() == 0) return nullptr; - TemplateArgumentKind kind; - CompilerType arg_type = type.GetTemplateArgument(0, kind); + CompilerType arg_type = type.GetTypeTemplateArgument(0); if (arg_type.GetTypeName() == ConstString("bool")) return new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp); return new LibcxxStdVectorSyntheticFrontEnd(valobj_sp); diff --git a/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp b/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp index e3018a1884be1..3e2b7159f8944 100644 --- a/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp +++ b/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp @@ -117,11 +117,8 @@ bool LibstdcppMapIteratorSyntheticFrontEnd::Update() { CompilerType my_type(valobj_sp->GetCompilerType()); if (my_type.GetNumTemplateArguments() >= 1) { - TemplateArgumentKind kind; - CompilerType pair_type = my_type.GetTemplateArgument(0, kind); - if (kind != eTemplateArgumentKindType && - kind != eTemplateArgumentKindTemplate && - kind != eTemplateArgumentKindTemplateExpansion) + CompilerType pair_type = my_type.GetTypeTemplateArgument(0); + if (!pair_type) return false; m_pair_type = pair_type; } else diff --git a/source/Plugins/Language/ObjC/CMakeLists.txt b/source/Plugins/Language/ObjC/CMakeLists.txt index 7cc93c7b05580..95ace3a3633ab 100644 --- a/source/Plugins/Language/ObjC/CMakeLists.txt +++ b/source/Plugins/Language/ObjC/CMakeLists.txt @@ -1,3 +1,13 @@ +set(EXTRA_CXXFLAGS "") + +if (CXX_SUPPORTS_NO_GNU_ANONYMOUS_STRUCT) + set(EXTRA_CXXFLAGS ${EXTRA_CXXFLAGS} -Wno-gnu-anonymous-struct) +endif () + +if (CXX_SUPPORTS_NO_NESTED_ANON_TYPES) + set(EXTRA_CXXFLAGS ${EXTRA_CXXFLAGS} -Wno-nested-anon-types) +endif () + add_lldb_library(lldbPluginObjCLanguage PLUGIN ObjCLanguage.cpp CF.cpp @@ -21,4 +31,6 @@ add_lldb_library(lldbPluginObjCLanguage PLUGIN lldbTarget lldbUtility lldbPluginAppleObjCRuntime + + EXTRA_CXXFLAGS ${EXTRA_CXXFLAGS} ) diff --git a/source/Plugins/Language/ObjC/NSArray.cpp b/source/Plugins/Language/ObjC/NSArray.cpp index 27cb9558c482d..f6d1592019511 100644 --- a/source/Plugins/Language/ObjC/NSArray.cpp +++ b/source/Plugins/Language/ObjC/NSArray.cpp @@ -48,11 +48,11 @@ NSArray_Additionals::GetAdditionalSynthetics() { return g_map; } -class NSArrayMSyntheticFrontEnd : public SyntheticChildrenFrontEnd { +class NSArrayMSyntheticFrontEndBase : public SyntheticChildrenFrontEnd { public: - NSArrayMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + NSArrayMSyntheticFrontEndBase(lldb::ValueObjectSP valobj_sp); - ~NSArrayMSyntheticFrontEnd() override = default; + ~NSArrayMSyntheticFrontEndBase() override = default; size_t CalculateNumChildren() override; @@ -78,11 +78,12 @@ protected: CompilerType m_id_type; }; -class NSArrayMSyntheticFrontEnd_109 : public NSArrayMSyntheticFrontEnd { +template <typename D32, typename D64> +class GenericNSArrayMSyntheticFrontEnd : public NSArrayMSyntheticFrontEndBase { public: - NSArrayMSyntheticFrontEnd_109(lldb::ValueObjectSP valobj_sp); + GenericNSArrayMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); - ~NSArrayMSyntheticFrontEnd_109() override; + ~GenericNSArrayMSyntheticFrontEnd() override; bool Update() override; @@ -96,6 +97,11 @@ protected: uint64_t GetSize() override; private: + D32 *m_data_32; + D64 *m_data_64; +}; + +namespace Foundation109 { struct DataDescriptor_32 { uint32_t _used; uint32_t _priv1 : 2; @@ -105,7 +111,7 @@ private: uint32_t _priv3; uint32_t _data; }; - + struct DataDescriptor_64 { uint64_t _used; uint64_t _priv1 : 2; @@ -115,29 +121,12 @@ private: uint32_t _priv3; uint64_t _data; }; - - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; -}; - -class NSArrayMSyntheticFrontEnd_1010 : public NSArrayMSyntheticFrontEnd { -public: - NSArrayMSyntheticFrontEnd_1010(lldb::ValueObjectSP valobj_sp); - - ~NSArrayMSyntheticFrontEnd_1010() override; - - bool Update() override; - -protected: - lldb::addr_t GetDataAddress() override; - - uint64_t GetUsedCount() override; - - uint64_t GetOffset() override; - - uint64_t GetSize() override; - -private: + + using NSArrayMSyntheticFrontEnd = + GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; +} + +namespace Foundation1010 { struct DataDescriptor_32 { uint32_t _used; uint32_t _offset; @@ -146,7 +135,7 @@ private: uint32_t _priv2; uint32_t _data; }; - + struct DataDescriptor_64 { uint64_t _used; uint64_t _offset; @@ -155,76 +144,86 @@ private: uint32_t _priv2; uint64_t _data; }; - - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; -}; - -class NSArrayMSyntheticFrontEnd_1400 : public NSArrayMSyntheticFrontEnd { -public: - NSArrayMSyntheticFrontEnd_1400(lldb::ValueObjectSP valobj_sp); - - ~NSArrayMSyntheticFrontEnd_1400() override; - - bool Update() override; - -protected: - lldb::addr_t GetDataAddress() override; - - uint64_t GetUsedCount() override; - - uint64_t GetOffset() override; - - uint64_t GetSize() override; - -private: + + using NSArrayMSyntheticFrontEnd = + GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; +} + +namespace Foundation1428 { struct DataDescriptor_32 { - uint32_t used; - uint32_t offset; - uint32_t size; - uint32_t list; + uint32_t _used; + uint32_t _offset; + uint32_t _size; + uint32_t _data; }; - + struct DataDescriptor_64 { - uint64_t used; - uint64_t offset; - uint64_t size; - uint64_t list; + uint64_t _used; + uint64_t _offset; + uint64_t _size; + uint64_t _data; }; + + using NSArrayMSyntheticFrontEnd = + GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; +} + +namespace Foundation1437 { + template <typename PtrType> + struct DataDescriptor { + PtrType _cow; + // __deque + PtrType _data; + uint32_t _offset; + uint32_t _size; + union { + PtrType _mutations; + struct { + uint32_t _muts; + uint32_t _used; + }; + }; + }; + + using NSArrayMSyntheticFrontEnd = + GenericNSArrayMSyntheticFrontEnd< + DataDescriptor<uint32_t>, DataDescriptor<uint64_t>>; + + template <typename DD> + uint64_t + __NSArrayMSize_Impl(lldb_private::Process &process, + lldb::addr_t valobj_addr, Status &error) { + const lldb::addr_t start_of_descriptor = + valobj_addr + process.GetAddressByteSize(); + DD descriptor = DD(); + process.ReadMemory(start_of_descriptor, &descriptor, + sizeof(descriptor), error); + if (error.Fail()) { + return 0; + } + return descriptor._used; + } + + uint64_t + __NSArrayMSize(lldb_private::Process &process, lldb::addr_t valobj_addr, + Status &error) { + if (process.GetAddressByteSize() == 4) { + return __NSArrayMSize_Impl<DataDescriptor<uint32_t>>(process, valobj_addr, + error); + } else { + return __NSArrayMSize_Impl<DataDescriptor<uint64_t>>(process, valobj_addr, + error); + } + } - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; -}; - -class NSArrayISyntheticFrontEnd_1300 : public SyntheticChildrenFrontEnd { -public: - NSArrayISyntheticFrontEnd_1300(lldb::ValueObjectSP valobj_sp); - - ~NSArrayISyntheticFrontEnd_1300() override = default; - - size_t CalculateNumChildren() override; - - lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; - - bool Update() override; - - bool MightHaveChildren() override; - - size_t GetIndexOfChildWithName(const ConstString &name) override; - -private: - ExecutionContextRef m_exe_ctx_ref; - uint8_t m_ptr_size; - uint64_t m_items; - lldb::addr_t m_data_ptr; - CompilerType m_id_type; -}; +} -class NSArrayISyntheticFrontEnd_1400 : public SyntheticChildrenFrontEnd { +template <typename D32, typename D64, bool Inline> +class GenericNSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: - NSArrayISyntheticFrontEnd_1400(lldb::ValueObjectSP valobj_sp); + GenericNSArrayISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); - ~NSArrayISyntheticFrontEnd_1400() override; + ~GenericNSArrayISyntheticFrontEnd() override; size_t CalculateNumChildren() override; @@ -239,25 +238,58 @@ public: private: ExecutionContextRef m_exe_ctx_ref; uint8_t m_ptr_size; - - struct DataDescriptor_32 { - uint32_t used; - uint32_t offset; - uint32_t size; - uint32_t list; - }; - - struct DataDescriptor_64 { - uint64_t used; - uint64_t offset; - uint64_t size; - uint64_t list; - }; - - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; + + D32 *m_data_32; + D64 *m_data_64; CompilerType m_id_type; }; + +namespace Foundation1300 { + struct IDD32 { + uint32_t used; + uint32_t list; + }; + + struct IDD64 { + uint64_t used; + uint64_t list; + }; + + using NSArrayISyntheticFrontEnd = + GenericNSArrayISyntheticFrontEnd<IDD32, IDD64, true>; +} + +namespace Foundation1430 { + using NSArrayISyntheticFrontEnd = + Foundation1428::NSArrayMSyntheticFrontEnd; +} + +namespace Foundation1436 { + struct IDD32 { + uint32_t used; + uint32_t list; // in Inline cases, this is the first element + }; + + struct IDD64 { + uint64_t used; + uint64_t list; // in Inline cases, this is the first element + }; + + using NSArrayI_TransferSyntheticFrontEnd = + GenericNSArrayISyntheticFrontEnd<IDD32, IDD64, false>; + + using NSArrayISyntheticFrontEnd = + GenericNSArrayISyntheticFrontEnd<IDD32, IDD64, true>; + + using NSFrozenArrayMSyntheticFrontEnd = + Foundation1437::NSArrayMSyntheticFrontEnd; + + uint64_t + __NSFrozenArrayMSize(lldb_private::Process &process, lldb::addr_t valobj_addr, + Status &error) { + return Foundation1437::__NSArrayMSize(process, valobj_addr, error); + } +} class NSArray0SyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: @@ -329,6 +361,8 @@ bool lldb_private::formatters::NSArraySummaryProvider( static const ConstString g_NSArrayI("__NSArrayI"); static const ConstString g_NSArrayM("__NSArrayM"); + static const ConstString g_NSArrayI_Transfer("__NSArrayI_Transfer"); + static const ConstString g_NSFrozenArrayM("__NSFrozenArrayM"); static const ConstString g_NSArray0("__NSArray0"); static const ConstString g_NSArray1("__NSSingleObjectArrayI"); static const ConstString g_NSArrayCF("__NSCFArray"); @@ -345,11 +379,28 @@ bool lldb_private::formatters::NSArraySummaryProvider( if (error.Fail()) return false; } else if (class_name == g_NSArrayM) { + AppleObjCRuntime *apple_runtime = + llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); + Status error; + if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) { + value = Foundation1437::__NSArrayMSize(*process_sp, valobj_addr, error); + } else { + value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, + ptr_size, 0, error); + } + if (error.Fail()) + return false; + } else if (class_name == g_NSArrayI_Transfer) { Status error; value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); if (error.Fail()) return false; + } else if (class_name == g_NSFrozenArrayM) { + Status error; + value = Foundation1436::__NSFrozenArrayMSize(*process_sp, valobj_addr, error); + if (error.Fail()) + return false; } else if (class_name == g_NSArrayMLegacy) { Status error; value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, @@ -395,7 +446,7 @@ bool lldb_private::formatters::NSArraySummaryProvider( return true; } -lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd( +lldb_private::formatters::NSArrayMSyntheticFrontEndBase::NSArrayMSyntheticFrontEndBase( lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), m_id_type() { @@ -411,28 +462,20 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd( } } -lldb_private::formatters::NSArrayMSyntheticFrontEnd_109:: - NSArrayMSyntheticFrontEnd_109(lldb::ValueObjectSP valobj_sp) - : NSArrayMSyntheticFrontEnd(valobj_sp), m_data_32(nullptr), - m_data_64(nullptr) {} - -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010:: - NSArrayMSyntheticFrontEnd_1010(lldb::ValueObjectSP valobj_sp) - : NSArrayMSyntheticFrontEnd(valobj_sp), m_data_32(nullptr), - m_data_64(nullptr) {} - -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400:: - NSArrayMSyntheticFrontEnd_1400(lldb::ValueObjectSP valobj_sp) - : NSArrayMSyntheticFrontEnd(valobj_sp), m_data_32(nullptr), +template <typename D32, typename D64> +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>:: + GenericNSArrayMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) + : NSArrayMSyntheticFrontEndBase(valobj_sp), m_data_32(nullptr), m_data_64(nullptr) {} size_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren() { +lldb_private::formatters::NSArrayMSyntheticFrontEndBase::CalculateNumChildren() { return GetUsedCount(); } lldb::ValueObjectSP -lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex( +lldb_private::formatters::NSArrayMSyntheticFrontEndBase::GetChildAtIndex( size_t idx) { if (idx >= CalculateNumChildren()) return lldb::ValueObjectSP(); @@ -448,69 +491,10 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex( m_exe_ctx_ref, m_id_type); } -bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::Update() { - ValueObjectSP valobj_sp = m_backend.GetSP(); - m_ptr_size = 0; - delete m_data_32; - m_data_32 = nullptr; - delete m_data_64; - m_data_64 = nullptr; - if (!valobj_sp) - return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - Status error; - error.Clear(); - lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); - if (!process_sp) - return false; - m_ptr_size = process_sp->GetAddressByteSize(); - uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; - if (m_ptr_size == 4) { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), - error); - } else { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), - error); - } - if (error.Fail()) - return false; - return false; -} - -bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::Update() { - ValueObjectSP valobj_sp = m_backend.GetSP(); - m_ptr_size = 0; - delete m_data_32; - m_data_32 = nullptr; - delete m_data_64; - m_data_64 = nullptr; - if (!valobj_sp) - return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - Status error; - error.Clear(); - lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); - if (!process_sp) - return false; - m_ptr_size = process_sp->GetAddressByteSize(); - uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; - if (m_ptr_size == 4) { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), - error); - } else { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), - error); - } - if (error.Fail()) - return false; - return false; -} - -bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::Update() { +template <typename D32, typename D64> +bool +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>::Update() { ValueObjectSP valobj_sp = m_backend.GetSP(); m_ptr_size = 0; delete m_data_32; @@ -528,12 +512,12 @@ bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::Update() { m_ptr_size = process_sp->GetAddressByteSize(); uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; if (m_ptr_size == 4) { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), + m_data_32 = new D32(); + process_sp->ReadMemory(data_location, m_data_32, sizeof(D32), error); } else { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), + m_data_64 = new D64(); + process_sp->ReadMemory(data_location, m_data_64, sizeof(D64), error); } if (error.Fail()) @@ -541,12 +525,13 @@ bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::Update() { return false; } -bool lldb_private::formatters::NSArrayMSyntheticFrontEnd::MightHaveChildren() { +bool +lldb_private::formatters::NSArrayMSyntheticFrontEndBase::MightHaveChildren() { return true; } size_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName( +lldb_private::formatters::NSArrayMSyntheticFrontEndBase::GetIndexOfChildWithName( const ConstString &name) { const char *item_name = name.GetCString(); uint32_t idx = ExtractIndexFromString(item_name); @@ -555,187 +540,59 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName( return idx; } -lldb_private::formatters::NSArrayMSyntheticFrontEnd_109:: - ~NSArrayMSyntheticFrontEnd_109() { +template <typename D32, typename D64> +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>:: + ~GenericNSArrayMSyntheticFrontEnd() { delete m_data_32; m_data_32 = nullptr; delete m_data_64; m_data_64 = nullptr; } +template <typename D32, typename D64> lldb::addr_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetDataAddress() { +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>:: + GenericNSArrayMSyntheticFrontEnd::GetDataAddress() { if (!m_data_32 && !m_data_64) return LLDB_INVALID_ADDRESS; return m_data_32 ? m_data_32->_data : m_data_64->_data; } +template <typename D32, typename D64> uint64_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetUsedCount() { +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>:: + GenericNSArrayMSyntheticFrontEnd::GetUsedCount() { if (!m_data_32 && !m_data_64) return 0; return m_data_32 ? m_data_32->_used : m_data_64->_used; } -uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetOffset() { - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->_offset : m_data_64->_offset; -} - -uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetSize() { - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->_size : m_data_64->_size; -} - -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010:: - ~NSArrayMSyntheticFrontEnd_1010() { - delete m_data_32; - m_data_32 = nullptr; - delete m_data_64; - m_data_64 = nullptr; -} - -lldb::addr_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetDataAddress() { - if (!m_data_32 && !m_data_64) - return LLDB_INVALID_ADDRESS; - return m_data_32 ? m_data_32->_data : m_data_64->_data; -} - +template <typename D32, typename D64> uint64_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetUsedCount() { - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->_used : m_data_64->_used; -} - -uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetOffset() { +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>:: + GenericNSArrayMSyntheticFrontEnd::GetOffset() { if (!m_data_32 && !m_data_64) return 0; return m_data_32 ? m_data_32->_offset : m_data_64->_offset; } -uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetSize() { - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->_size : m_data_64->_size; -} - -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400:: - ~NSArrayMSyntheticFrontEnd_1400() { - delete m_data_32; - m_data_32 = nullptr; - delete m_data_64; - m_data_64 = nullptr; -} - -lldb::addr_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetDataAddress() { - if (!m_data_32 && !m_data_64) - return LLDB_INVALID_ADDRESS; - return m_data_32 ? m_data_32->list : m_data_64->list; -} - +template <typename D32, typename D64> uint64_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetUsedCount() { +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>:: + GenericNSArrayMSyntheticFrontEnd::GetSize() { if (!m_data_32 && !m_data_64) return 0; - return m_data_32 ? m_data_32->used : m_data_64->used; -} - -uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetOffset() { - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->offset : m_data_64->offset; -} - -uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetSize() { - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->size : m_data_64->size; -} - - -lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::NSArrayISyntheticFrontEnd_1300( - lldb::ValueObjectSP valobj_sp) - : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), - m_items(0), m_data_ptr(0) { - if (valobj_sp) { - CompilerType type = valobj_sp->GetCompilerType(); - if (type) { - ClangASTContext *ast = valobj_sp->GetExecutionContextRef() - .GetTargetSP() - ->GetScratchClangASTContext(); - if (ast) - m_id_type = CompilerType(ast->getASTContext(), - ast->getASTContext()->ObjCBuiltinIdTy); - } - } -} - -size_t -lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::GetIndexOfChildWithName( - const ConstString &name) { - const char *item_name = name.GetCString(); - uint32_t idx = ExtractIndexFromString(item_name); - if (idx < UINT32_MAX && idx >= CalculateNumChildren()) - return UINT32_MAX; - return idx; -} - -size_t -lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::CalculateNumChildren() { - return m_items; -} - -bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::Update() { - m_ptr_size = 0; - m_items = 0; - m_data_ptr = 0; - ValueObjectSP valobj_sp = m_backend.GetSP(); - if (!valobj_sp) - return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - Status error; - error.Clear(); - lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); - if (!process_sp) - return false; - m_ptr_size = process_sp->GetAddressByteSize(); - uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; - m_items = process_sp->ReadPointerFromMemory(data_location, error); - if (error.Fail()) - return false; - m_data_ptr = data_location + m_ptr_size; - return false; -} - -bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::MightHaveChildren() { - return true; -} - -lldb::ValueObjectSP -lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::GetChildAtIndex( - size_t idx) { - if (idx >= CalculateNumChildren()) - return lldb::ValueObjectSP(); - lldb::addr_t object_at_idx = m_data_ptr; - object_at_idx += (idx * m_ptr_size); - ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); - if (!process_sp) - return lldb::ValueObjectSP(); - Status error; - if (error.Fail()) - return lldb::ValueObjectSP(); - StreamString idx_name; - idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); - return CreateValueObjectFromAddress(idx_name.GetString(), object_at_idx, - m_exe_ctx_ref, m_id_type); + return m_data_32 ? m_data_32->_size : m_data_64->_size; } -lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::NSArrayISyntheticFrontEnd_1400( +template <typename D32, typename D64, bool Inline> +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + GenericNSArrayISyntheticFrontEnd( lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), m_data_32(nullptr), m_data_64(nullptr) { @@ -752,16 +609,19 @@ lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::NSArrayISyntheticFront } } -lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::~NSArrayISyntheticFrontEnd_1400() { +template <typename D32, typename D64, bool Inline> +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + ~GenericNSArrayISyntheticFrontEnd() { delete m_data_32; m_data_32 = nullptr; delete m_data_64; m_data_64 = nullptr; } +template <typename D32, typename D64, bool Inline> size_t -lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::GetIndexOfChildWithName( - const ConstString &name) { +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + GetIndexOfChildWithName(const ConstString &name) { const char *item_name = name.GetCString(); uint32_t idx = ExtractIndexFromString(item_name); if (idx < UINT32_MAX && idx >= CalculateNumChildren()) @@ -769,12 +629,17 @@ lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::GetIndexOfChildWithNam return idx; } +template <typename D32, typename D64, bool Inline> size_t -lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::CalculateNumChildren() { +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + CalculateNumChildren() { return m_data_32 ? m_data_32->used : m_data_64->used; } -bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::Update() { +template <typename D32, typename D64, bool Inline> +bool +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + Update() { ValueObjectSP valobj_sp = m_backend.GetSP(); m_ptr_size = 0; delete m_data_32; @@ -792,12 +657,12 @@ bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::Update() { m_ptr_size = process_sp->GetAddressByteSize(); uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; if (m_ptr_size == 4) { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), + m_data_32 = new D32(); + process_sp->ReadMemory(data_location, m_data_32, sizeof(D32), error); } else { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), + m_data_64 = new D64(); + process_sp->ReadMemory(data_location, m_data_64, sizeof(D64), error); } if (error.Fail()) @@ -805,17 +670,29 @@ bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::Update() { return false; } -bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::MightHaveChildren() { +template <typename D32, typename D64, bool Inline> +bool +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + MightHaveChildren() { return true; } +template <typename D32, typename D64, bool Inline> lldb::ValueObjectSP -lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::GetChildAtIndex( - size_t idx) { +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + GetChildAtIndex(size_t idx) { if (idx >= CalculateNumChildren()) return lldb::ValueObjectSP(); - lldb::addr_t object_at_idx = m_data_32 ? m_data_32->list : m_data_64->list; + lldb::addr_t object_at_idx; + if (Inline) { + object_at_idx = m_backend.GetSP()->GetValueAsUnsigned(0) + m_ptr_size; + object_at_idx += m_ptr_size == 4 ? sizeof(D32) : sizeof(D64); // skip the data header + object_at_idx -= m_ptr_size; // we treat the last entry in the data header as the first pointer + } else { + object_at_idx = m_data_32 ? m_data_32->list : m_data_64->list; + } object_at_idx += (idx * m_ptr_size); + ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); if (!process_sp) return lldb::ValueObjectSP(); @@ -933,6 +810,8 @@ lldb_private::formatters::NSArraySyntheticFrontEndCreator( ConstString class_name(descriptor->GetClassName()); static const ConstString g_NSArrayI("__NSArrayI"); + static const ConstString g_NSArrayI_Transfer("__NSArrayI_Transfer"); + static const ConstString g_NSFrozenArrayM("__NSFrozenArrayM"); static const ConstString g_NSArrayM("__NSArrayM"); static const ConstString g_NSArray0("__NSArray0"); static const ConstString g_NSArray1("__NSSingleObjectArrayI"); @@ -943,21 +822,30 @@ lldb_private::formatters::NSArraySyntheticFrontEndCreator( return nullptr; if (class_name == g_NSArrayI) { - if (runtime->GetFoundationVersion() >= 1400) - return (new NSArrayISyntheticFrontEnd_1400(valobj_sp)); - else - return (new NSArrayISyntheticFrontEnd_1300(valobj_sp)); + if (runtime->GetFoundationVersion() >= 1436) + return (new Foundation1436::NSArrayISyntheticFrontEnd(valobj_sp)); + if (runtime->GetFoundationVersion() >= 1430) + return (new Foundation1430::NSArrayISyntheticFrontEnd(valobj_sp)); + else + return (new Foundation1300::NSArrayISyntheticFrontEnd(valobj_sp)); + } else if (class_name == g_NSArrayI_Transfer) { + return (new Foundation1436::NSArrayI_TransferSyntheticFrontEnd(valobj_sp)); + } else if (class_name == g_NSArray0) { + } else if (class_name == g_NSFrozenArrayM) { + return (new Foundation1436::NSFrozenArrayMSyntheticFrontEnd(valobj_sp)); } else if (class_name == g_NSArray0) { return (new NSArray0SyntheticFrontEnd(valobj_sp)); } else if (class_name == g_NSArray1) { return (new NSArray1SyntheticFrontEnd(valobj_sp)); } else if (class_name == g_NSArrayM) { - if (runtime->GetFoundationVersion() >= 1400) - return (new NSArrayMSyntheticFrontEnd_1400(valobj_sp)); + if (runtime->GetFoundationVersion() >= 1437) + return (new Foundation1437::NSArrayMSyntheticFrontEnd(valobj_sp)); + if (runtime->GetFoundationVersion() >= 1428) + return (new Foundation1428::NSArrayMSyntheticFrontEnd(valobj_sp)); if (runtime->GetFoundationVersion() >= 1100) - return (new NSArrayMSyntheticFrontEnd_1010(valobj_sp)); + return (new Foundation1010::NSArrayMSyntheticFrontEnd(valobj_sp)); else - return (new NSArrayMSyntheticFrontEnd_109(valobj_sp)); + return (new Foundation109::NSArrayMSyntheticFrontEnd(valobj_sp)); } else { auto &map(NSArray_Additionals::GetAdditionalSynthetics()); auto iter = map.find(class_name), end = map.end(); diff --git a/source/Plugins/Language/ObjC/NSDictionary.cpp b/source/Plugins/Language/ObjC/NSDictionary.cpp index 50febbe397583..c564aa1a85715 100644 --- a/source/Plugins/Language/ObjC/NSDictionary.cpp +++ b/source/Plugins/Language/ObjC/NSDictionary.cpp @@ -165,11 +165,12 @@ private: ValueObjectSP m_pair; }; -class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd { +template <typename D32, typename D64> +class GenericNSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: - NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + GenericNSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); - ~NSDictionaryMSyntheticFrontEnd() override; + ~GenericNSDictionaryMSyntheticFrontEnd() override; size_t CalculateNumChildren() override; @@ -182,20 +183,6 @@ public: size_t GetIndexOfChildWithName(const ConstString &name) override; private: - struct DataDescriptor_32 { - uint32_t used : 26; - uint32_t kvo : 1; - uint32_t size; - uint32_t buffer; - }; - - struct DataDescriptor_64 { - uint64_t used : 58; - uint32_t kvo : 1; - uint64_t size; - uint64_t buffer; - }; - struct DictionaryItemDescriptor { lldb::addr_t key_ptr; lldb::addr_t val_ptr; @@ -205,61 +192,169 @@ private: ExecutionContextRef m_exe_ctx_ref; uint8_t m_ptr_size; lldb::ByteOrder m_order; - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; + D32 *m_data_32; + D64 *m_data_64; CompilerType m_pair_type; std::vector<DictionaryItemDescriptor> m_children; }; - -class NSDictionaryMLegacySyntheticFrontEnd : public SyntheticChildrenFrontEnd { -public: - NSDictionaryMLegacySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); - - ~NSDictionaryMLegacySyntheticFrontEnd() override; - - size_t CalculateNumChildren() override; - - lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; - - bool Update() override; - - bool MightHaveChildren() override; - - size_t GetIndexOfChildWithName(const ConstString &name) override; - -private: + +namespace Foundation1100 { + class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd { + public: + NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + + ~NSDictionaryMSyntheticFrontEnd() override; + + size_t CalculateNumChildren() override; + + lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; + + bool Update() override; + + bool MightHaveChildren() override; + + size_t GetIndexOfChildWithName(const ConstString &name) override; + + private: + struct DataDescriptor_32 { + uint32_t _used : 26; + uint32_t _kvo : 1; + uint32_t _size; + uint32_t _mutations; + uint32_t _objs_addr; + uint32_t _keys_addr; + }; + + struct DataDescriptor_64 { + uint64_t _used : 58; + uint32_t _kvo : 1; + uint64_t _size; + uint64_t _mutations; + uint64_t _objs_addr; + uint64_t _keys_addr; + }; + + struct DictionaryItemDescriptor { + lldb::addr_t key_ptr; + lldb::addr_t val_ptr; + lldb::ValueObjectSP valobj_sp; + }; + + ExecutionContextRef m_exe_ctx_ref; + uint8_t m_ptr_size; + lldb::ByteOrder m_order; + DataDescriptor_32 *m_data_32; + DataDescriptor_64 *m_data_64; + CompilerType m_pair_type; + std::vector<DictionaryItemDescriptor> m_children; + }; +} + +namespace Foundation1428 { struct DataDescriptor_32 { uint32_t _used : 26; uint32_t _kvo : 1; uint32_t _size; - uint32_t _mutations; - uint32_t _objs_addr; - uint32_t _keys_addr; + uint32_t _buffer; + uint64_t GetSize() { return _size; } }; - + struct DataDescriptor_64 { uint64_t _used : 58; uint32_t _kvo : 1; uint64_t _size; - uint64_t _mutations; - uint64_t _objs_addr; - uint64_t _keys_addr; + uint64_t _buffer; + uint64_t GetSize() { return _size; } }; - - struct DictionaryItemDescriptor { - lldb::addr_t key_ptr; - lldb::addr_t val_ptr; - lldb::ValueObjectSP valobj_sp; + + + + using NSDictionaryMSyntheticFrontEnd = + GenericNSDictionaryMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; +} + +namespace Foundation1437 { + static const uint64_t NSDictionaryCapacities[] = { + 0, 3, 7, 13, 23, 41, 71, 127, 191, 251, 383, 631, 1087, 1723, + 2803, 4523, 7351, 11959, 19447, 31231, 50683, 81919, 132607, + 214519, 346607, 561109, 907759, 1468927, 2376191, 3845119, + 6221311, 10066421, 16287743, 26354171, 42641881, 68996069, + 111638519, 180634607, 292272623, 472907251 + }; + + static const size_t NSDictionaryNumSizeBuckets = sizeof(NSDictionaryCapacities) / sizeof(uint64_t); + + struct DataDescriptor_32 { + uint32_t _buffer; + union { + struct { + uint32_t _mutations; + }; + struct { + uint32_t _muts; + uint32_t _used:25; + uint32_t _kvo:1; + uint32_t _szidx:6; + }; + }; + + uint64_t GetSize() { + return (_szidx) >= NSDictionaryNumSizeBuckets ? + 0 : NSDictionaryCapacities[_szidx]; + } }; + + struct DataDescriptor_64 { + uint64_t _buffer; + union { + struct { + uint64_t _mutations; + }; + struct { + uint32_t _muts; + uint32_t _used:25; + uint32_t _kvo:1; + uint32_t _szidx:6; + }; + }; + + uint64_t GetSize() { + return (_szidx) >= NSDictionaryNumSizeBuckets ? + 0 : NSDictionaryCapacities[_szidx]; + } + }; + + using NSDictionaryMSyntheticFrontEnd = + GenericNSDictionaryMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; + + template <typename DD> + uint64_t + __NSDictionaryMSize_Impl(lldb_private::Process &process, + lldb::addr_t valobj_addr, Status &error) { + const lldb::addr_t start_of_descriptor = + valobj_addr + process.GetAddressByteSize(); + DD descriptor = DD(); + process.ReadMemory(start_of_descriptor, &descriptor, sizeof(descriptor), + error); + if (error.Fail()) { + return 0; + } + return descriptor._used; + } + + uint64_t + __NSDictionaryMSize(lldb_private::Process &process, lldb::addr_t valobj_addr, + Status &error) { + if (process.GetAddressByteSize() == 4) { + return __NSDictionaryMSize_Impl<DataDescriptor_32>(process, valobj_addr, + error); + } else { + return __NSDictionaryMSize_Impl<DataDescriptor_64>(process, valobj_addr, + error); + } + } - ExecutionContextRef m_exe_ctx_ref; - uint8_t m_ptr_size; - lldb::ByteOrder m_order; - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; - CompilerType m_pair_type; - std::vector<DictionaryItemDescriptor> m_children; -}; +} } // namespace formatters } // namespace lldb_private @@ -313,12 +408,19 @@ bool lldb_private::formatters::NSDictionarySummaryProvider( return false; value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy) { + AppleObjCRuntime *apple_runtime = + llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); Status error; - value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, - ptr_size, 0, error); + if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) { + value = Foundation1437::__NSDictionaryMSize(*process_sp, valobj_addr, + error); + } else { + value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, + ptr_size, 0, error); + value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); + } if (error.Fail()) return false; - value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); } else if (class_name == g_Dictionary1) { value = 1; } @@ -396,13 +498,15 @@ lldb_private::formatters::NSDictionarySyntheticFrontEndCreator( if (class_name == g_DictionaryI) { return (new NSDictionaryISyntheticFrontEnd(valobj_sp)); } else if (class_name == g_DictionaryM) { - if (runtime->GetFoundationVersion() > 1400) { - return (new NSDictionaryMSyntheticFrontEnd(valobj_sp)); + if (runtime->GetFoundationVersion() >= 1437) { + return (new Foundation1437::NSDictionaryMSyntheticFrontEnd(valobj_sp)); + } else if (runtime->GetFoundationVersion() >= 1428) { + return (new Foundation1428::NSDictionaryMSyntheticFrontEnd(valobj_sp)); } else { - return (new NSDictionaryMLegacySyntheticFrontEnd(valobj_sp)); + return (new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp)); } } else if (class_name == g_DictionaryMLegacy) { - return (new NSDictionaryMLegacySyntheticFrontEnd(valobj_sp)); + return (new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp)); } else if (class_name == g_Dictionary1) { return (new NSDictionary1SyntheticFrontEnd(valobj_sp)); } else { @@ -641,22 +745,25 @@ lldb_private::formatters::NSDictionary1SyntheticFrontEnd::GetChildAtIndex( return m_pair; } -lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: - NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) +template <typename D32, typename D64> +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>:: + GenericNSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), m_order(lldb::eByteOrderInvalid), m_data_32(nullptr), m_data_64(nullptr), m_pair_type() {} -lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: - ~NSDictionaryMSyntheticFrontEnd() { +template <typename D32, typename D64> +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>:: + ~GenericNSDictionaryMSyntheticFrontEnd() { delete m_data_32; m_data_32 = nullptr; delete m_data_64; m_data_64 = nullptr; } -size_t lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: - GetIndexOfChildWithName(const ConstString &name) { +template <typename D32, typename D64> +size_t +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>:: GetIndexOfChildWithName(const ConstString &name) { const char *item_name = name.GetCString(); uint32_t idx = ExtractIndexFromString(item_name); if (idx < UINT32_MAX && idx >= CalculateNumChildren()) @@ -664,14 +771,18 @@ size_t lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: return idx; } -size_t lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: - CalculateNumChildren() { +template <typename D32, typename D64> +size_t +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>::CalculateNumChildren() { if (!m_data_32 && !m_data_64) return 0; - return (m_data_32 ? m_data_32->used : m_data_64->used); + return (m_data_32 ? m_data_32->_used : m_data_64->_used); } -bool lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update() { +template <typename D32, typename D64> +bool +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>:: + Update() { m_children.clear(); ValueObjectSP valobj_sp = m_backend.GetSP(); m_ptr_size = 0; @@ -691,12 +802,12 @@ bool lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update() { m_order = process_sp->GetByteOrder(); uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; if (m_ptr_size == 4) { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), + m_data_32 = new D32(); + process_sp->ReadMemory(data_location, m_data_32, sizeof(D32), error); } else { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), + m_data_64 = new D64(); + process_sp->ReadMemory(data_location, m_data_64, sizeof(D64), error); } if (error.Fail()) @@ -704,24 +815,28 @@ bool lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update() { return false; } -bool lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: +template <typename D32, typename D64> +bool +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>:: MightHaveChildren() { return true; } +template <typename D32, typename D64> lldb::ValueObjectSP -lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex( +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>:: + GetChildAtIndex( size_t idx) { lldb::addr_t m_keys_ptr; lldb::addr_t m_values_ptr; if (m_data_32) { - uint32_t size = m_data_32->size; - m_keys_ptr = m_data_32->buffer; - m_values_ptr = m_data_32->buffer + (m_ptr_size * size); + uint32_t size = m_data_32->GetSize(); + m_keys_ptr = m_data_32->_buffer; + m_values_ptr = m_data_32->_buffer + (m_ptr_size * size); } else { - uint32_t size = m_data_64->size; - m_keys_ptr = m_data_64->buffer; - m_values_ptr = m_data_64->buffer + (m_ptr_size * size); + uint32_t size = m_data_64->GetSize(); + m_keys_ptr = m_data_64->_buffer; + m_values_ptr = m_data_64->_buffer + (m_ptr_size * size); } uint32_t num_children = CalculateNumChildren(); @@ -800,22 +915,24 @@ lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex( } -lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: - NSDictionaryMLegacySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd:: + NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), m_order(lldb::eByteOrderInvalid), m_data_32(nullptr), m_data_64(nullptr), m_pair_type() {} -lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: - ~NSDictionaryMLegacySyntheticFrontEnd() { +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd::~NSDictionaryMSyntheticFrontEnd() { delete m_data_32; m_data_32 = nullptr; delete m_data_64; m_data_64 = nullptr; } -size_t lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: - GetIndexOfChildWithName(const ConstString &name) { +size_t +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd::GetIndexOfChildWithName(const ConstString &name) { const char *item_name = name.GetCString(); uint32_t idx = ExtractIndexFromString(item_name); if (idx < UINT32_MAX && idx >= CalculateNumChildren()) @@ -823,14 +940,17 @@ size_t lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: return idx; } -size_t lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: - CalculateNumChildren() { +size_t +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd::CalculateNumChildren() { if (!m_data_32 && !m_data_64) return 0; return (m_data_32 ? m_data_32->_used : m_data_64->_used); } -bool lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::Update() { +bool +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd::Update() { m_children.clear(); ValueObjectSP valobj_sp = m_backend.GetSP(); m_ptr_size = 0; @@ -863,14 +983,15 @@ bool lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::Update() { return false; } -bool lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: - MightHaveChildren() { +bool +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd::MightHaveChildren() { return true; } lldb::ValueObjectSP -lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::GetChildAtIndex( - size_t idx) { +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd::GetChildAtIndex(size_t idx) { lldb::addr_t m_keys_ptr = (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr); lldb::addr_t m_values_ptr = diff --git a/source/Plugins/Language/ObjC/NSSet.cpp b/source/Plugins/Language/ObjC/NSSet.cpp index 2f33987751699..fa2483ecc0947 100644 --- a/source/Plugins/Language/ObjC/NSSet.cpp +++ b/source/Plugins/Language/ObjC/NSSet.cpp @@ -135,7 +135,7 @@ namespace Foundation1300 { GenericNSSetMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; } -namespace Foundation1400 { +namespace Foundation1428 { struct DataDescriptor_32 { uint32_t _used : 26; uint32_t _size; @@ -154,6 +154,64 @@ namespace Foundation1400 { GenericNSSetMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; } +namespace Foundation1437 { + struct DataDescriptor_32 { + uint32_t _cow; + // __table storage + uint32_t _objs_addr; + union { + uint32_t _mutations; + struct { + uint32_t _muts; + uint32_t _used : 26; + uint32_t _szidx : 6; + }; + }; + }; + + struct DataDescriptor_64 { + uint64_t _cow; + // __Table storage + uint64_t _objs_addr; + union { + uint64_t _mutations; + struct { + uint32_t _muts; + uint32_t _used : 26; + uint32_t _szidx : 6; + }; + }; + }; + + using NSSetMSyntheticFrontEnd = + GenericNSSetMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; + + template <typename DD> + uint64_t + __NSSetMSize_Impl(lldb_private::Process &process, lldb::addr_t valobj_addr, + Status &error) { + const lldb::addr_t start_of_descriptor = + valobj_addr + process.GetAddressByteSize(); + DD descriptor = DD(); + process.ReadMemory(start_of_descriptor, &descriptor, sizeof(descriptor), + error); + if (error.Fail()) { + return 0; + } + return descriptor._used; + } + + uint64_t + __NSSetMSize(lldb_private::Process &process, lldb::addr_t valobj_addr, + Status &error) { + if (process.GetAddressByteSize() == 4) { + return __NSSetMSize_Impl<DataDescriptor_32>(process, valobj_addr, error); + } else { + return __NSSetMSize_Impl<DataDescriptor_64>(process, valobj_addr, error); + } + } +} + class NSSetCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: NSSetCodeRunningSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); @@ -219,12 +277,18 @@ bool lldb_private::formatters::NSSetSummaryProvider( return false; value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); } else if (!strcmp(class_name, "__NSSetM")) { + AppleObjCRuntime *apple_runtime = + llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); Status error; - value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, - ptr_size, 0, error); + if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) { + value = Foundation1437::__NSSetMSize(*process_sp, valobj_addr, error); + } else { + value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, + ptr_size, 0, error); + value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); + } if (error.Fail()) return false; - value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); } /*else if (!strcmp(class_name,"__NSCFSet")) { @@ -312,10 +376,16 @@ lldb_private::formatters::NSSetSyntheticFrontEndCreator( } else if (!strcmp(class_name, "__NSSetM")) { AppleObjCRuntime *apple_runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); - if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1400) - return (new Foundation1400::NSSetMSyntheticFrontEnd(valobj_sp)); - else + if (apple_runtime) { + if (apple_runtime->GetFoundationVersion() >= 1437) + return (new Foundation1437::NSSetMSyntheticFrontEnd(valobj_sp)); + else if (apple_runtime->GetFoundationVersion() >= 1428) + return (new Foundation1428::NSSetMSyntheticFrontEnd(valobj_sp)); + else + return (new Foundation1300::NSSetMSyntheticFrontEnd(valobj_sp)); + } else { return (new Foundation1300::NSSetMSyntheticFrontEnd(valobj_sp)); + } } else { auto &map(NSSet_Additionals::GetAdditionalSynthetics()); auto iter = map.find(class_name_cs), end = map.end(); diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp index e99fd74a352f4..105c088b9e913 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp @@ -324,8 +324,6 @@ public: clang::ASTContext &ast_ctx(interface_decl->getASTContext()); - clang::QualType return_qual_type; - const bool isInstance = instance; const bool isVariadic = false; const bool isSynthesized = false; @@ -653,3 +651,11 @@ AppleObjCDeclVendor::FindDecls(const ConstString &name, bool append, return ret; } + +clang::ExternalASTMerger::ImporterSource +AppleObjCDeclVendor::GetImporterSource() { + return {*m_ast_ctx.getASTContext(), + *m_ast_ctx.getFileManager(), + m_ast_ctx.GetOriginMap() + }; +} diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h index 26824079d945e..2f087da16bc18 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h @@ -30,6 +30,8 @@ public: uint32_t FindDecls(const ConstString &name, bool append, uint32_t max_matches, std::vector<clang::NamedDecl *> &decls) override; + clang::ExternalASTMerger::ImporterSource GetImporterSource() override; + friend class AppleObjCExternalASTSource; private: diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h index 57d98fbd72834..1b22ee4c3be17 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h @@ -95,6 +95,8 @@ public: virtual void GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true, lldb::addr_t &cf_false); + + virtual bool IsTaggedPointer (lldb::addr_t addr) { return false; } protected: // Call CreateInstance instead. diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 2a7735959a910..bdf79f7b82bd1 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -62,6 +62,11 @@ #include "AppleObjCTrampolineHandler.h" #include "AppleObjCTypeEncodingParser.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclObjC.h" + +#include <vector> + using namespace lldb; using namespace lldb_private; @@ -394,7 +399,7 @@ AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process, } bool AppleObjCRuntimeV2::GetDynamicTypeAndAddress( - ValueObject &in_value, DynamicValueType use_dynamic, + ValueObject &in_value, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, Address &address, Value::ValueType &value_type) { // We should never get here with a null process... @@ -811,85 +816,43 @@ UtilityFunction *AppleObjCRuntimeV2::CreateObjectChecker(const char *name) { int len = 0; if (m_has_object_getClass) { - len = ::snprintf(check_function_code, sizeof(check_function_code), - "extern \"C\" void *gdb_object_getClass(void *); " - " \n" - "extern \"C\" int printf(const char *format, ...); " - " \n" - "extern \"C\" void " - " \n" - "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) " - " \n" - "{ " - " \n" - " if ($__lldb_arg_obj == (void *)0) " - " \n" - " return; // nil is ok " - " \n" - " if (!gdb_object_getClass($__lldb_arg_obj)) " - " \n" - " *((volatile int *)0) = 'ocgc'; " - " \n" - " else if ($__lldb_arg_selector != (void *)0) " - " \n" - " { " - " \n" - " signed char responds = (signed char) [(id) " - "$__lldb_arg_obj \n" - " " - "respondsToSelector: \n" - " (struct " - "objc_selector *) $__lldb_arg_selector]; \n" - " if (responds == (signed char) 0) " - " \n" - " *((volatile int *)0) = 'ocgc'; " - " \n" - " } " - " \n" - "} " - " \n", - name); + len = ::snprintf(check_function_code, sizeof(check_function_code), R"( + extern "C" void *gdb_object_getClass(void *); + extern "C" int printf(const char *format, ...); + extern "C" void + %s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) { + if ($__lldb_arg_obj == (void *)0) + return; // nil is ok + if (!gdb_object_getClass($__lldb_arg_obj)) { + *((volatile int *)0) = 'ocgc'; + } else if ($__lldb_arg_selector != (void *)0) { + signed char $responds = (signed char) + [(id)$__lldb_arg_obj respondsToSelector: + (void *) $__lldb_arg_selector]; + if ($responds == (signed char) 0) + *((volatile int *)0) = 'ocgc'; + } + })", name); } else { - len = ::snprintf(check_function_code, sizeof(check_function_code), - "extern \"C\" void *gdb_class_getClass(void *); " - " \n" - "extern \"C\" int printf(const char *format, ...); " - " \n" - "extern \"C\" void " - " \n" - "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) " - " \n" - "{ " - " \n" - " if ($__lldb_arg_obj == (void *)0) " - " \n" - " return; // nil is ok " - " \n" - " void **$isa_ptr = (void **)$__lldb_arg_obj; " - " \n" - " if (*$isa_ptr == (void *)0 || " - "!gdb_class_getClass(*$isa_ptr)) \n" - " *((volatile int *)0) = 'ocgc'; " - " \n" - " else if ($__lldb_arg_selector != (void *)0) " - " \n" - " { " - " \n" - " signed char responds = (signed char) [(id) " - "$__lldb_arg_obj \n" - " " - "respondsToSelector: \n" - " (struct " - "objc_selector *) $__lldb_arg_selector]; \n" - " if (responds == (signed char) 0) " - " \n" - " *((volatile int *)0) = 'ocgc'; " - " \n" - " } " - " \n" - "} " - " \n", - name); + len = ::snprintf(check_function_code, sizeof(check_function_code), R"( + extern "C" void *gdb_class_getClass(void *); + extern "C" int printf(const char *format, ...); + extern "C" void + %s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) { + if ($__lldb_arg_obj == (void *)0) + return; // nil is ok + void **$isa_ptr = (void **)$__lldb_arg_obj; + if (*$isa_ptr == (void *)0 || + !gdb_class_getClass(*$isa_ptr)) + *((volatile int *)0) = 'ocgc'; + else if ($__lldb_arg_selector != (void *)0) { + signed char $responds = (signed char) + [(id)$__lldb_arg_obj respondsToSelector: + (void *) $__lldb_arg_selector]; + if ($responds == (signed char) 0) + *((volatile int *)0) = 'ocgc'; + } + })", name); } assert(len < (int)sizeof(check_function_code)); @@ -2022,6 +1985,8 @@ AppleObjCRuntimeV2::NonPointerISACache::CreateInstance( Status error; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES)); + auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol( process, ConstString("objc_debug_isa_magic_mask"), objc_module_sp, error); if (error.Fail()) @@ -2038,12 +2003,47 @@ AppleObjCRuntimeV2::NonPointerISACache::CreateInstance( if (error.Fail()) return NULL; + if (log) + log->PutCString("AOCRT::NPI: Found all the non-indexed ISA masks"); + + bool foundError = false; + auto objc_debug_indexed_isa_magic_mask = ExtractRuntimeGlobalSymbol( + process, ConstString("objc_debug_indexed_isa_magic_mask"), objc_module_sp, + error); + foundError |= error.Fail(); + + auto objc_debug_indexed_isa_magic_value = ExtractRuntimeGlobalSymbol( + process, ConstString("objc_debug_indexed_isa_magic_value"), + objc_module_sp, error); + foundError |= error.Fail(); + + auto objc_debug_indexed_isa_index_mask = ExtractRuntimeGlobalSymbol( + process, ConstString("objc_debug_indexed_isa_index_mask"), objc_module_sp, + error); + foundError |= error.Fail(); + + auto objc_debug_indexed_isa_index_shift = ExtractRuntimeGlobalSymbol( + process, ConstString("objc_debug_indexed_isa_index_shift"), + objc_module_sp, error); + foundError |= error.Fail(); + + auto objc_indexed_classes = + ExtractRuntimeGlobalSymbol(process, ConstString("objc_indexed_classes"), + objc_module_sp, error, false); + foundError |= error.Fail(); + + if (log) + log->PutCString("AOCRT::NPI: Found all the indexed ISA masks"); + // we might want to have some rules to outlaw these other values (e.g if the // mask is zero but the value is non-zero, ...) - return new NonPointerISACache(runtime, objc_debug_isa_class_mask, - objc_debug_isa_magic_mask, - objc_debug_isa_magic_value); + return new NonPointerISACache( + runtime, objc_module_sp, objc_debug_isa_class_mask, + objc_debug_isa_magic_mask, objc_debug_isa_magic_value, + objc_debug_indexed_isa_magic_mask, objc_debug_indexed_isa_magic_value, + objc_debug_indexed_isa_index_mask, objc_debug_indexed_isa_index_shift, + foundError ? 0 : objc_indexed_classes); } AppleObjCRuntimeV2::TaggedPointerVendorV2 * @@ -2371,12 +2371,23 @@ AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor( } AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache( - AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_isa_class_mask, - uint64_t objc_debug_isa_magic_mask, uint64_t objc_debug_isa_magic_value) - : m_runtime(runtime), m_cache(), + AppleObjCRuntimeV2 &runtime, const ModuleSP &objc_module_sp, + uint64_t objc_debug_isa_class_mask, uint64_t objc_debug_isa_magic_mask, + uint64_t objc_debug_isa_magic_value, + uint64_t objc_debug_indexed_isa_magic_mask, + uint64_t objc_debug_indexed_isa_magic_value, + uint64_t objc_debug_indexed_isa_index_mask, + uint64_t objc_debug_indexed_isa_index_shift, + lldb::addr_t objc_indexed_classes) + : m_runtime(runtime), m_cache(), m_objc_module_wp(objc_module_sp), m_objc_debug_isa_class_mask(objc_debug_isa_class_mask), m_objc_debug_isa_magic_mask(objc_debug_isa_magic_mask), - m_objc_debug_isa_magic_value(objc_debug_isa_magic_value) {} + m_objc_debug_isa_magic_value(objc_debug_isa_magic_value), + m_objc_debug_indexed_isa_magic_mask(objc_debug_indexed_isa_magic_mask), + m_objc_debug_indexed_isa_magic_value(objc_debug_indexed_isa_magic_value), + m_objc_debug_indexed_isa_index_mask(objc_debug_indexed_isa_index_mask), + m_objc_debug_indexed_isa_index_shift(objc_debug_indexed_isa_index_shift), + m_objc_indexed_classes(objc_indexed_classes), m_indexed_isa_cache() {} ObjCLanguageRuntime::ClassDescriptorSP AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor(ObjCISA isa) { @@ -2395,8 +2406,106 @@ AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor(ObjCISA isa) { bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA( ObjCISA isa, ObjCISA &ret_isa) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES)); + + if (log) + log->Printf("AOCRT::NPI Evalulate(isa = 0x%" PRIx64 ")", (uint64_t)isa); + if ((isa & ~m_objc_debug_isa_class_mask) == 0) return false; + + // If all of the indexed ISA variables are set, then its possible that + // this ISA is indexed, and we should first try to get its value using + // the index. + // Note, we check these varaibles first as the ObjC runtime will set at + // least one of their values to 0 if they aren't needed. + if (m_objc_debug_indexed_isa_magic_mask && + m_objc_debug_indexed_isa_magic_value && + m_objc_debug_indexed_isa_index_mask && + m_objc_debug_indexed_isa_index_shift && m_objc_indexed_classes) { + if ((isa & ~m_objc_debug_indexed_isa_index_mask) == 0) + return false; + + if ((isa & m_objc_debug_indexed_isa_magic_mask) == + m_objc_debug_indexed_isa_magic_value) { + // Magic bits are correct, so try extract the index. + uintptr_t index = (isa & m_objc_debug_indexed_isa_index_mask) >> + m_objc_debug_indexed_isa_index_shift; + // If the index is out of bounds of the length of the array then + // check if the array has been updated. If that is the case then + // we should try read the count again, and update the cache if the + // count has been updated. + if (index > m_indexed_isa_cache.size()) { + if (log) + log->Printf("AOCRT::NPI (index = %" PRIu64 + ") exceeds cache (size = %" PRIu64 ")", + (uint64_t)index, (uint64_t)m_indexed_isa_cache.size()); + + Process *process(m_runtime.GetProcess()); + + ModuleSP objc_module_sp(m_objc_module_wp.lock()); + if (!objc_module_sp) + return false; + + Status error; + auto objc_indexed_classes_count = ExtractRuntimeGlobalSymbol( + process, ConstString("objc_indexed_classes_count"), objc_module_sp, + error); + if (error.Fail()) + return false; + + if (log) + log->Printf("AOCRT::NPI (new class count = %" PRIu64 ")", + (uint64_t)objc_indexed_classes_count); + + if (objc_indexed_classes_count > m_indexed_isa_cache.size()) { + // Read the class entries we don't have. We should just + // read all of them instead of just the one we need as then + // we can cache those we may need later. + auto num_new_classes = + objc_indexed_classes_count - m_indexed_isa_cache.size(); + const uint32_t addr_size = process->GetAddressByteSize(); + DataBufferHeap buffer(num_new_classes * addr_size, 0); + + lldb::addr_t last_read_class = + m_objc_indexed_classes + (m_indexed_isa_cache.size() * addr_size); + size_t bytes_read = process->ReadMemory( + last_read_class, buffer.GetBytes(), buffer.GetByteSize(), error); + if (error.Fail() || bytes_read != buffer.GetByteSize()) + return false; + + if (log) + log->Printf("AOCRT::NPI (read new classes count = %" PRIu64 ")", + (uint64_t)num_new_classes); + + // Append the new entries to the existing cache. + DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(), + process->GetByteOrder(), + process->GetAddressByteSize()); + + lldb::offset_t offset = 0; + for (unsigned i = 0; i != num_new_classes; ++i) + m_indexed_isa_cache.push_back(data.GetPointer(&offset)); + } + } + + // If the index is still out of range then this isn't a pointer. + if (index > m_indexed_isa_cache.size()) + return false; + + if (log) + log->Printf("AOCRT::NPI Evalulate(ret_isa = 0x%" PRIx64 ")", + (uint64_t)m_indexed_isa_cache[index]); + + ret_isa = m_indexed_isa_cache[index]; + return (ret_isa != 0); // this is a pointer so 0 is not a valid value + } + + return false; + } + + // Definately not an indexed ISA, so try to use a mask to extract + // the pointer from the ISA. if ((isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value) { ret_isa = isa & m_objc_debug_isa_class_mask; return (ret_isa != 0); // this is a pointer so 0 is not a valid value diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h index 7180730904062..89e81d5b181e1 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h @@ -88,6 +88,8 @@ public: EncodingToTypeSP GetEncodingToType() override; + bool IsTaggedPointer(lldb::addr_t ptr) override; + TaggedPointerVendor *GetTaggedPointerVendor() override { return m_tagged_pointer_vendor_ap.get(); } @@ -138,18 +140,33 @@ private: private: NonPointerISACache(AppleObjCRuntimeV2 &runtime, + const lldb::ModuleSP &objc_module_sp, uint64_t objc_debug_isa_class_mask, uint64_t objc_debug_isa_magic_mask, - uint64_t objc_debug_isa_magic_value); + uint64_t objc_debug_isa_magic_value, + uint64_t objc_debug_indexed_isa_magic_mask, + uint64_t objc_debug_indexed_isa_magic_value, + uint64_t objc_debug_indexed_isa_index_mask, + uint64_t objc_debug_indexed_isa_index_shift, + lldb::addr_t objc_indexed_classes); bool EvaluateNonPointerISA(ObjCISA isa, ObjCISA &ret_isa); AppleObjCRuntimeV2 &m_runtime; std::map<ObjCISA, ObjCLanguageRuntime::ClassDescriptorSP> m_cache; + lldb::ModuleWP m_objc_module_wp; uint64_t m_objc_debug_isa_class_mask; uint64_t m_objc_debug_isa_magic_mask; uint64_t m_objc_debug_isa_magic_value; + uint64_t m_objc_debug_indexed_isa_magic_mask; + uint64_t m_objc_debug_indexed_isa_magic_value; + uint64_t m_objc_debug_indexed_isa_index_mask; + uint64_t m_objc_debug_indexed_isa_index_shift; + lldb::addr_t m_objc_indexed_classes; + + std::vector<lldb::addr_t> m_indexed_isa_cache; + friend class AppleObjCRuntimeV2; DISALLOW_COPY_AND_ASSIGN(NonPointerISACache); @@ -279,8 +296,6 @@ private: ObjCISA GetPointerISA(ObjCISA isa); - bool IsTaggedPointer(lldb::addr_t ptr); - lldb::addr_t GetISAHashTablePointer(); bool UpdateISAToDescriptorMapFromMemory(RemoteNXMapTable &hash_table); diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp index 7e46afcccdab3..ad1083be02850 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp @@ -3615,13 +3615,15 @@ RenderScriptRuntime::CreateKernelBreakpoint(const ConstString &name) { } BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name)); - BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint( + Target &target = GetProcess()->GetTarget(); + BreakpointSP bp = target.CreateBreakpoint( m_filtersp, resolver_sp, false, false, false); // Give RS breakpoints a specific name, so the user can manipulate them as a // group. Status err; - if (!bp->AddName("RenderScriptKernel", err)) + target.AddNameToBreakpoint(bp, "RenderScriptKernel", err); + if (err.Fail() && log) if (log) log->Printf("%s - error setting break name, '%s'.", __FUNCTION__, err.AsCString()); @@ -3643,14 +3645,15 @@ RenderScriptRuntime::CreateReductionBreakpoint(const ConstString &name, BreakpointResolverSP resolver_sp(new RSReduceBreakpointResolver( nullptr, name, &m_rsmodules, kernel_types)); - BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint( + Target &target = GetProcess()->GetTarget(); + BreakpointSP bp = target.CreateBreakpoint( m_filtersp, resolver_sp, false, false, false); // Give RS breakpoints a specific name, so the user can manipulate them as a // group. Status err; - if (!bp->AddName("RenderScriptReduction", err)) - if (log) + target.AddNameToBreakpoint(bp, "RenderScriptReduction", err); + if (err.Fail() && log) log->Printf("%s - error setting break name, '%s'.", __FUNCTION__, err.AsCString()); @@ -3885,15 +3888,16 @@ RenderScriptRuntime::CreateScriptGroupBreakpoint(const ConstString &name, BreakpointResolverSP resolver_sp(new RSScriptGroupBreakpointResolver( nullptr, name, m_scriptGroups, stop_on_all)); - BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint( + Target &target = GetProcess()->GetTarget(); + BreakpointSP bp = target.CreateBreakpoint( m_filtersp, resolver_sp, false, false, false); // Give RS breakpoints a specific name, so the user can manipulate them as a // group. Status err; - if (!bp->AddName(name.AsCString(), err)) - if (log) - log->Printf("%s - error setting break name, '%s'.", __FUNCTION__, - err.AsCString()); + target.AddNameToBreakpoint(bp, name.GetCString(), err); + if (err.Fail() && log) + log->Printf("%s - error setting break name, '%s'.", __FUNCTION__, + err.AsCString()); // ask the breakpoint to resolve itself bp->ResolveBreakpoint(); return bp; diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp index 25bfce7a2b835..d7bef836d9d87 100644 --- a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp +++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp @@ -27,12 +27,12 @@ typedef struct ar_hdr { #include <ar.h> #endif -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Host/FileSystem.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataBufferLLVM.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/Timer.h" diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h index 0e10d47f2ce46..cb63eccff65e5 100644 --- a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h +++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h @@ -10,10 +10,9 @@ #ifndef liblldb_ObjectContainerBSDArchive_h_ #define liblldb_ObjectContainerBSDArchive_h_ -// Project includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/UniqueCStringMap.h" #include "lldb/Symbol/ObjectContainer.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/FileSpec.h" diff --git a/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp b/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp index 31eb17873f3e4..0266bbe27e7d7 100644 --- a/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp +++ b/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp @@ -8,12 +8,12 @@ //===----------------------------------------------------------------------===// #include "ObjectContainerUniversalMachO.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/Stream.h" diff --git a/source/Plugins/ObjectFile/ELF/CMakeLists.txt b/source/Plugins/ObjectFile/ELF/CMakeLists.txt index e0680b07efc55..45a4edcbb1c9e 100644 --- a/source/Plugins/ObjectFile/ELF/CMakeLists.txt +++ b/source/Plugins/ObjectFile/ELF/CMakeLists.txt @@ -9,5 +9,6 @@ add_lldb_library(lldbPluginObjectFileELF PLUGIN lldbTarget LINK_COMPONENTS BinaryFormat + Object Support ) diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 3b33cf1601fb7..17d892450e4de 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -13,7 +13,6 @@ #include <cassert> #include <unordered_map> -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/FileSpecList.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" @@ -23,6 +22,8 @@ #include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataBufferLLVM.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" @@ -31,6 +32,7 @@ #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Object/Decompressor.h" #include "llvm/Support/ARMBuildAttributes.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" @@ -405,7 +407,7 @@ ObjectFile *ObjectFileELF::CreateInstance(const lldb::ModuleSP &module_sp, lldb::offset_t length) { if (!data_sp) { data_sp = - DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset); + DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset, true); if (!data_sp) return nullptr; data_offset = 0; @@ -423,7 +425,7 @@ ObjectFile *ObjectFileELF::CreateInstance(const lldb::ModuleSP &module_sp, // Update the data to contain the entire file if it doesn't already if (data_sp->GetByteSize() < length) { data_sp = - DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset); + DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset, true); if (!data_sp) return nullptr; data_offset = 0; @@ -451,7 +453,7 @@ ObjectFile *ObjectFileELF::CreateMemoryInstance( if (ELFHeader::MagicBytesMatch(magic)) { unsigned address_size = ELFHeader::AddressSizeInBytes(magic); if (address_size == 4 || address_size == 8) { - std::auto_ptr<ObjectFileELF> objfile_ap( + std::unique_ptr<ObjectFileELF> objfile_ap( new ObjectFileELF(module_sp, data_sp, process_sp, header_addr)); ArchSpec spec; if (objfile_ap->GetArchitecture(spec) && @@ -1818,6 +1820,12 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { if (!m_sections_ap.get() && ParseSectionHeaders()) { m_sections_ap.reset(new SectionList()); + // Object files frequently have 0 for every section address, meaning we + // need to compute synthetic addresses in order for "file addresses" from + // different sections to not overlap + bool synthaddrs = (CalculateType() == ObjectFile::Type::eTypeObjectFile); + uint64_t nextaddr = 0; + for (SectionHeaderCollIter I = m_section_headers.begin(); I != m_section_headers.end(); ++I) { const ELFSectionHeaderInfo &header = *I; @@ -1835,6 +1843,7 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { static ConstString g_sect_name_dwarf_debug_abbrev(".debug_abbrev"); static ConstString g_sect_name_dwarf_debug_addr(".debug_addr"); static ConstString g_sect_name_dwarf_debug_aranges(".debug_aranges"); + static ConstString g_sect_name_dwarf_debug_cu_index(".debug_cu_index"); static ConstString g_sect_name_dwarf_debug_frame(".debug_frame"); static ConstString g_sect_name_dwarf_debug_info(".debug_info"); static ConstString g_sect_name_dwarf_debug_line(".debug_line"); @@ -1904,6 +1913,8 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { sect_type = eSectionTypeDWARFDebugAddr; else if (name == g_sect_name_dwarf_debug_aranges) sect_type = eSectionTypeDWARFDebugAranges; + else if (name == g_sect_name_dwarf_debug_cu_index) + sect_type = eSectionTypeDWARFDebugCuIndex; else if (name == g_sect_name_dwarf_debug_frame) sect_type = eSectionTypeDWARFDebugFrame; else if (name == g_sect_name_dwarf_debug_info) @@ -1987,9 +1998,18 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { ? m_arch_spec.GetDataByteSize() : eSectionTypeCode == sect_type ? m_arch_spec.GetCodeByteSize() : 1; - elf::elf_xword log2align = (header.sh_addralign == 0) ? 0 : llvm::Log2_64(header.sh_addralign); + + uint64_t addr = header.sh_addr; + + if ((header.sh_flags & SHF_ALLOC) && synthaddrs) { + nextaddr = + (nextaddr + header.sh_addralign - 1) & ~(header.sh_addralign - 1); + addr = nextaddr; + nextaddr += vm_size; + } + SectionSP section_sp(new Section( GetModule(), // Module to which this section belongs. this, // ObjectFile to which this section belongs and should read @@ -1997,7 +2017,7 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { SectionIndex(I), // Section ID. name, // Section name. sect_type, // Section type. - header.sh_addr, // VM address. + addr, // VM address. vm_size, // VM size in bytes of this section. header.sh_offset, // Offset of this section in the file. file_size, // Size of the section as found in the file. @@ -2015,13 +2035,14 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { if (m_sections_ap.get()) { if (GetType() == eTypeDebugInfo) { static const SectionType g_sections[] = { - eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr, - eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugFrame, - eSectionTypeDWARFDebugInfo, eSectionTypeDWARFDebugLine, - eSectionTypeDWARFDebugLoc, eSectionTypeDWARFDebugMacInfo, - eSectionTypeDWARFDebugPubNames, eSectionTypeDWARFDebugPubTypes, - eSectionTypeDWARFDebugRanges, eSectionTypeDWARFDebugStr, - eSectionTypeDWARFDebugStrOffsets, eSectionTypeELFSymbolTable, + eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr, + eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugCuIndex, + eSectionTypeDWARFDebugFrame, eSectionTypeDWARFDebugInfo, + eSectionTypeDWARFDebugLine, eSectionTypeDWARFDebugLoc, + eSectionTypeDWARFDebugMacInfo, eSectionTypeDWARFDebugPubNames, + eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges, + eSectionTypeDWARFDebugStr, eSectionTypeDWARFDebugStrOffsets, + eSectionTypeELFSymbolTable, }; SectionList *elf_section_list = m_sections_ap.get(); for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]); @@ -2714,7 +2735,7 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table, user_id_t start_id, rel_data, symtab_data, strtab_data); } -unsigned ObjectFileELF::RelocateSection( +unsigned ObjectFileELF::ApplyRelocations( Symtab *symtab, const ELFHeader *hdr, const ELFSectionHeader *rel_hdr, const ELFSectionHeader *symtab_hdr, const ELFSectionHeader *debug_hdr, DataExtractor &rel_data, DataExtractor &symtab_data, @@ -2745,6 +2766,14 @@ unsigned ObjectFileELF::RelocateSection( case R_386_32: case R_386_PC32: default: + // FIXME: This asserts with this input: + // + // foo.cpp + // int main(int argc, char **argv) { return 0; } + // + // clang++.exe --target=i686-unknown-linux-gnu -g -c foo.cpp -o foo.o + // + // and running this on the foo.o module. assert(false && "unexpected relocation type"); } } else { @@ -2791,7 +2820,8 @@ unsigned ObjectFileELF::RelocateSection( } unsigned ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr, - user_id_t rel_id) { + user_id_t rel_id, + lldb_private::Symtab *thetab) { assert(rel_hdr->sh_type == SHT_RELA || rel_hdr->sh_type == SHT_REL); // Parse in the section list if needed. @@ -2827,10 +2857,11 @@ unsigned ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr, DataExtractor symtab_data; DataExtractor debug_data; - if (ReadSectionData(rel, rel_data) && ReadSectionData(symtab, symtab_data) && - ReadSectionData(debug, debug_data)) { - RelocateSection(m_symtab_ap.get(), &m_header, rel_hdr, symtab_hdr, - debug_hdr, rel_data, symtab_data, debug_data, debug); + if (GetData(rel->GetFileOffset(), rel->GetFileSize(), rel_data) && + GetData(symtab->GetFileOffset(), symtab->GetFileSize(), symtab_data) && + GetData(debug->GetFileOffset(), debug->GetFileSize(), debug_data)) { + ApplyRelocations(thetab, &m_header, rel_hdr, symtab_hdr, debug_hdr, + rel_data, symtab_data, debug_data, debug); } return 0; @@ -2924,21 +2955,48 @@ Symtab *ObjectFileELF::GetSymtab() { m_symtab_ap->CalculateSymbolSizes(); } + return m_symtab_ap.get(); +} + +void ObjectFileELF::RelocateSection(lldb_private::Section *section) +{ + static const char *debug_prefix = ".debug"; + + // Set relocated bit so we stop getting called, regardless of + // whether we actually relocate. + section->SetIsRelocated(true); + + // We only relocate in ELF relocatable files + if (CalculateType() != eTypeObjectFile) + return; + + const char *section_name = section->GetName().GetCString(); + // Can't relocate that which can't be named + if (section_name == nullptr) + return; + + // We don't relocate non-debug sections at the moment + if (strncmp(section_name, debug_prefix, strlen(debug_prefix))) + return; + + // Relocation section names to look for + std::string needle = std::string(".rel") + section_name; + std::string needlea = std::string(".rela") + section_name; + for (SectionHeaderCollIter I = m_section_headers.begin(); I != m_section_headers.end(); ++I) { if (I->sh_type == SHT_RELA || I->sh_type == SHT_REL) { - if (CalculateType() == eTypeObjectFile) { - const char *section_name = I->section_name.AsCString(""); - if (strstr(section_name, ".rela.debug") || - strstr(section_name, ".rel.debug")) { - const ELFSectionHeader &reloc_header = *I; - user_id_t reloc_id = SectionIndex(I); - RelocateDebugSections(&reloc_header, reloc_id); - } + const char *hay_name = I->section_name.GetCString(); + if (hay_name == nullptr) + continue; + if (needle == hay_name || needlea == hay_name) { + const ELFSectionHeader &reloc_header = *I; + user_id_t reloc_id = SectionIndex(I); + RelocateDebugSections(&reloc_header, reloc_id, GetSymtab()); + break; } } } - return m_symtab_ap.get(); } void ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table, @@ -3404,3 +3462,56 @@ ObjectFile::Strata ObjectFileELF::CalculateStrata() { } return eStrataUnknown; } + +size_t ObjectFileELF::ReadSectionData(Section *section, + lldb::offset_t section_offset, void *dst, + size_t dst_len) { + // If some other objectfile owns this data, pass this to them. + if (section->GetObjectFile() != this) + return section->GetObjectFile()->ReadSectionData(section, section_offset, + dst, dst_len); + + if (!section->Test(SHF_COMPRESSED)) + return ObjectFile::ReadSectionData(section, section_offset, dst, dst_len); + + // For compressed sections we need to read to full data to be able to + // decompress. + DataExtractor data; + ReadSectionData(section, data); + return data.CopyData(section_offset, dst_len, dst); +} + +size_t ObjectFileELF::ReadSectionData(Section *section, + DataExtractor §ion_data) { + // If some other objectfile owns this data, pass this to them. + if (section->GetObjectFile() != this) + return section->GetObjectFile()->ReadSectionData(section, section_data); + + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES); + + size_t result = ObjectFile::ReadSectionData(section, section_data); + if (result == 0 || !section->Test(SHF_COMPRESSED)) + return result; + + auto Decompressor = llvm::object::Decompressor::create( + section->GetName().GetStringRef(), + {reinterpret_cast<const char *>(section_data.GetDataStart()), + size_t(section_data.GetByteSize())}, + GetByteOrder() == eByteOrderLittle, GetAddressByteSize() == 8); + if (!Decompressor) { + LLDB_LOG(log, "Unable to initialize decompressor for section {0}: {1}", + section->GetName(), llvm::toString(Decompressor.takeError())); + return result; + } + auto buffer_sp = + std::make_shared<DataBufferHeap>(Decompressor->getDecompressedSize(), 0); + if (auto Error = Decompressor->decompress( + {reinterpret_cast<char *>(buffer_sp->GetBytes()), + size_t(buffer_sp->GetByteSize())})) { + LLDB_LOG(log, "Decompression of section {0} failed: {1}", + section->GetName(), llvm::toString(std::move(Error))); + return result; + } + section_data.SetData(buffer_sp); + return buffer_sp->GetByteSize(); +} diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index 6d8717b0ef25e..2909f4e52e4aa 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -16,10 +16,8 @@ // C++ Includes #include <vector> -// Other libraries and framework includes -// Project includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/UUID.h" #include "lldb/lldb-private.h" @@ -142,6 +140,13 @@ public: ObjectFile::Strata CalculateStrata() override; + size_t ReadSectionData(lldb_private::Section *section, + lldb::offset_t section_offset, void *dst, + size_t dst_len) override; + + size_t ReadSectionData(lldb_private::Section *section, + lldb_private::DataExtractor §ion_data) override; + // Returns number of program headers found in the ELF file. size_t GetProgramHeaderCount(); @@ -154,6 +159,8 @@ public: llvm::StringRef StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const override; + void RelocateSection(lldb_private::Section *section) override; + private: ObjectFileELF(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, lldb::offset_t data_offset, const lldb_private::FileSpec *file, @@ -296,17 +303,18 @@ private: /// Relocates debug sections unsigned RelocateDebugSections(const elf::ELFSectionHeader *rel_hdr, - lldb::user_id_t rel_id); - - unsigned RelocateSection(lldb_private::Symtab *symtab, - const elf::ELFHeader *hdr, - const elf::ELFSectionHeader *rel_hdr, - const elf::ELFSectionHeader *symtab_hdr, - const elf::ELFSectionHeader *debug_hdr, - lldb_private::DataExtractor &rel_data, - lldb_private::DataExtractor &symtab_data, - lldb_private::DataExtractor &debug_data, - lldb_private::Section *rel_section); + lldb::user_id_t rel_id, + lldb_private::Symtab *thetab); + + unsigned ApplyRelocations(lldb_private::Symtab *symtab, + const elf::ELFHeader *hdr, + const elf::ELFSectionHeader *rel_hdr, + const elf::ELFSectionHeader *symtab_hdr, + const elf::ELFSectionHeader *debug_hdr, + lldb_private::DataExtractor &rel_data, + lldb_private::DataExtractor &symtab_data, + lldb_private::DataExtractor &debug_data, + lldb_private::Section *rel_section); /// Loads the section name string table into m_shstr_data. Returns the /// number of bytes constituting the table. diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp index 06406c6f16556..a9ab366fbf53e 100644 --- a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp +++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp @@ -10,8 +10,6 @@ #include "llvm/ADT/StringRef.h" #include "ObjectFileJIT.h" - -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/FileSpecList.h" #include "lldb/Core/Module.h" @@ -26,6 +24,7 @@ #include "lldb/Target/Process.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/FileSpec.h" @@ -230,9 +229,9 @@ bool ObjectFileJIT::SetLoadAddress(Target &target, lldb::addr_t value, return num_loaded_sections > 0; } -size_t ObjectFileJIT::ReadSectionData(const lldb_private::Section *section, +size_t ObjectFileJIT::ReadSectionData(lldb_private::Section *section, lldb::offset_t section_offset, void *dst, - size_t dst_len) const { + size_t dst_len) { lldb::offset_t file_size = section->GetFileSize(); if (section_offset < file_size) { size_t src_len = file_size - section_offset; @@ -248,8 +247,8 @@ size_t ObjectFileJIT::ReadSectionData(const lldb_private::Section *section, } size_t ObjectFileJIT::ReadSectionData( - const lldb_private::Section *section, - lldb_private::DataExtractor §ion_data) const { + lldb_private::Section *section, + lldb_private::DataExtractor §ion_data) { if (section->GetFileSize()) { const void *src = (void *)(uintptr_t)section->GetFileOffset(); diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h index a211645d5d8b3..c964906a5e8e7 100644 --- a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h +++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h @@ -83,13 +83,13 @@ public: uint32_t GetDependentModules(lldb_private::FileSpecList &files) override; - size_t ReadSectionData(const lldb_private::Section *section, + size_t ReadSectionData(lldb_private::Section *section, lldb::offset_t section_offset, void *dst, - size_t dst_len) const override; + size_t dst_len) override; size_t - ReadSectionData(const lldb_private::Section *section, - lldb_private::DataExtractor §ion_data) const override; + ReadSectionData(lldb_private::Section *section, + lldb_private::DataExtractor §ion_data) override; lldb_private::Address GetEntryPointAddress() override; diff --git a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index 9bc171e454c98..df334f88ee3b4 100644 --- a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -17,7 +17,6 @@ #include "Plugins/Process/Utility/RegisterContextDarwin_arm64.h" #include "Plugins/Process/Utility/RegisterContextDarwin_i386.h" #include "Plugins/Process/Utility/RegisterContextDarwin_x86_64.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/FileSpecList.h" #include "lldb/Core/Module.h" @@ -38,6 +37,7 @@ #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadList.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataBufferLLVM.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" @@ -686,7 +686,7 @@ public: case FPURegSet: { uint8_t *fpu_reg_buf = (uint8_t *)&fpu.v[0]; const int fpu_reg_buf_size = sizeof(fpu); - if (fpu_reg_buf_size == count && + if (fpu_reg_buf_size == count * sizeof(uint32_t) && data.ExtractBytes(offset, fpu_reg_buf_size, eByteOrderLittle, fpu_reg_buf) == fpu_reg_buf_size) { SetError(FPURegSet, Read, 0); @@ -1200,6 +1200,7 @@ AddressClass ObjectFileMachO::GetAddressClass(lldb::addr_t file_addr) { case eSectionTypeDWARFDebugAbbrev: case eSectionTypeDWARFDebugAddr: case eSectionTypeDWARFDebugAranges: + case eSectionTypeDWARFDebugCuIndex: case eSectionTypeDWARFDebugFrame: case eSectionTypeDWARFDebugInfo: case eSectionTypeDWARFDebugLine: diff --git a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp index 5607a71ad5aab..72b1b15f08f86 100644 --- a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -10,9 +10,6 @@ #include "ObjectFilePECOFF.h" #include "WindowsMiniDump.h" -#include "llvm/BinaryFormat/COFF.h" - -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/FileSpecList.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" @@ -23,12 +20,14 @@ #include "lldb/Target/Process.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataBufferLLVM.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" #include "lldb/Utility/UUID.h" +#include "llvm/BinaryFormat/COFF.h" #include "llvm/Support/MemoryBuffer.h" @@ -136,6 +135,11 @@ size_t ObjectFilePECOFF::GetModuleSpecifications( spec.SetTriple("i686-pc-windows"); specs.Append(ModuleSpec(file, spec)); } + else if (coff_header.machine == MachineArmNt) + { + spec.SetTriple("arm-pc-windows"); + specs.Append(ModuleSpec(file, spec)); + } } } } @@ -537,7 +541,8 @@ Symtab *ObjectFilePECOFF::GetSymtab() { // First 4 bytes should be zeroed after strtab_size has been read, // because it is used as offset 0 to encode a NULL string. - uint32_t *strtab_data_start = (uint32_t *)strtab_data.GetDataStart(); + uint32_t *strtab_data_start = const_cast<uint32_t *>( + reinterpret_cast<const uint32_t *>(strtab_data.GetDataStart())); strtab_data_start[0] = 0; offset = 0; diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp index 588f3f7aec645..b71f3cf04c33f 100644 --- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp +++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp @@ -17,7 +17,6 @@ #include "Plugins/Process/Utility/RegisterContextDummy.h" #include "Plugins/Process/Utility/RegisterContextMemory.h" #include "Plugins/Process/Utility/ThreadMemory.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" diff --git a/source/Plugins/Platform/Android/AdbClient.cpp b/source/Plugins/Platform/Android/AdbClient.cpp index d3bcee6f487d7..6e15eb2b1dcb6 100644 --- a/source/Plugins/Platform/Android/AdbClient.cpp +++ b/source/Plugins/Platform/Android/AdbClient.cpp @@ -46,7 +46,7 @@ using namespace std::chrono; namespace { -const seconds kReadTimeout(12); +const seconds kReadTimeout(20); const char *kOKAY = "OKAY"; const char *kFAIL = "FAIL"; const char *kDATA = "DATA"; diff --git a/source/Plugins/Platform/Android/PlatformAndroid.cpp b/source/Plugins/Platform/Android/PlatformAndroid.cpp index 0f37da60d5d61..5b85bcdf7fdd1 100644 --- a/source/Plugins/Platform/Android/PlatformAndroid.cpp +++ b/source/Plugins/Platform/Android/PlatformAndroid.cpp @@ -21,6 +21,7 @@ #include "AdbClient.h" #include "PlatformAndroid.h" #include "PlatformAndroidRemoteGDBServer.h" +#include "lldb/Target/Target.h" using namespace lldb; using namespace lldb_private; @@ -366,9 +367,22 @@ bool PlatformAndroid::GetRemoteOSVersion() { return m_major_os_version != 0; } -llvm::StringRef PlatformAndroid::GetLibdlFunctionDeclarations() { +llvm::StringRef +PlatformAndroid::GetLibdlFunctionDeclarations(lldb_private::Process *process) { + SymbolContextList matching_symbols; + std::vector<const char *> dl_open_names = { "__dl_dlopen", "dlopen" }; + const char *dl_open_name = nullptr; + Target &target = process->GetTarget(); + for (auto name: dl_open_names) { + if (target.GetImages().FindFunctionSymbols(ConstString(name), + eFunctionNameTypeFull, + matching_symbols)) { + dl_open_name = name; + break; + } + } // Older platform versions have the dl function symbols mangled - if (GetSdkVersion() < 26) + if (dl_open_name == dl_open_names[0]) return R"( extern "C" void* dlopen(const char*, int) asm("__dl_dlopen"); extern "C" void* dlsym(void*, const char*) asm("__dl_dlsym"); @@ -376,7 +390,7 @@ llvm::StringRef PlatformAndroid::GetLibdlFunctionDeclarations() { extern "C" char* dlerror(void) asm("__dl_dlerror"); )"; - return PlatformPOSIX::GetLibdlFunctionDeclarations(); + return PlatformPOSIX::GetLibdlFunctionDeclarations(process); } AdbClient::SyncService *PlatformAndroid::GetSyncService(Status &error) { diff --git a/source/Plugins/Platform/Android/PlatformAndroid.h b/source/Plugins/Platform/Android/PlatformAndroid.h index 638dba9733698..4c12eb8c016da 100644 --- a/source/Plugins/Platform/Android/PlatformAndroid.h +++ b/source/Plugins/Platform/Android/PlatformAndroid.h @@ -76,7 +76,8 @@ protected: Status DownloadSymbolFile(const lldb::ModuleSP &module_sp, const FileSpec &dst_file_spec) override; - llvm::StringRef GetLibdlFunctionDeclarations() override; + llvm::StringRef + GetLibdlFunctionDeclarations(lldb_private::Process *process) override; private: AdbClient::SyncService *GetSyncService(Status &error); diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp index 53cec45f986e6..73c7d21f0a069 100644 --- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp +++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp @@ -314,13 +314,19 @@ void PlatformFreeBSD::CalculateTrapHandlerSymbolNames() { m_trap_handlers.push_back(ConstString("_sigtramp")); } -uint64_t PlatformFreeBSD::ConvertMmapFlagsToPlatform(const ArchSpec &arch, - unsigned flags) { +MmapArgList PlatformFreeBSD::GetMmapArgumentList(const ArchSpec &arch, + addr_t addr, addr_t length, + unsigned prot, unsigned flags, + addr_t fd, addr_t offset) { uint64_t flags_platform = 0; if (flags & eMmapFlagsPrivate) flags_platform |= MAP_PRIVATE; if (flags & eMmapFlagsAnon) flags_platform |= MAP_ANON; - return flags_platform; + + MmapArgList args({addr, length, prot, flags_platform, fd, offset}); + if (arch.GetTriple().getArch() == llvm::Triple::x86) + args.push_back(0); + return args; } diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h index 4bde2148a4d41..274304834290b 100644 --- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h +++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h @@ -61,8 +61,10 @@ public: void CalculateTrapHandlerSymbolNames() override; - uint64_t ConvertMmapFlagsToPlatform(const ArchSpec &arch, - unsigned flags) override; + MmapArgList GetMmapArgumentList(const ArchSpec &arch, lldb::addr_t addr, + lldb::addr_t length, unsigned prot, + unsigned flags, lldb::addr_t fd, + lldb::addr_t offset) override; private: DISALLOW_COPY_AND_ASSIGN(PlatformFreeBSD); diff --git a/source/Plugins/Platform/Linux/PlatformLinux.cpp b/source/Plugins/Platform/Linux/PlatformLinux.cpp index 0bf00ea307984..8186eae0e8c41 100644 --- a/source/Plugins/Platform/Linux/PlatformLinux.cpp +++ b/source/Plugins/Platform/Linux/PlatformLinux.cpp @@ -372,7 +372,7 @@ PlatformLinux::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, // Hook up process PTY if we have one (which we should for local debugging // with llgs). int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); - if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd) { + if (pty_fd != PseudoTerminal::invalid_fd) { process_sp->SetSTDIOFileDescriptor(pty_fd); LLDB_LOG(log, "hooked up STDIO pty to process"); } else @@ -390,8 +390,10 @@ void PlatformLinux::CalculateTrapHandlerSymbolNames() { m_trap_handlers.push_back(ConstString("_sigtramp")); } -uint64_t PlatformLinux::ConvertMmapFlagsToPlatform(const ArchSpec &arch, - unsigned flags) { +MmapArgList PlatformLinux::GetMmapArgumentList(const ArchSpec &arch, + addr_t addr, addr_t length, + unsigned prot, unsigned flags, + addr_t fd, addr_t offset) { uint64_t flags_platform = 0; uint64_t map_anon = MAP_ANON; @@ -406,6 +408,8 @@ uint64_t PlatformLinux::ConvertMmapFlagsToPlatform(const ArchSpec &arch, flags_platform |= MAP_PRIVATE; if (flags & eMmapFlagsAnon) flags_platform |= map_anon; - return flags_platform; + + MmapArgList args({addr, length, prot, flags_platform, fd, offset}); + return args; } diff --git a/source/Plugins/Platform/Linux/PlatformLinux.h b/source/Plugins/Platform/Linux/PlatformLinux.h index bc7b723427f8d..50d721f7c0723 100644 --- a/source/Plugins/Platform/Linux/PlatformLinux.h +++ b/source/Plugins/Platform/Linux/PlatformLinux.h @@ -59,8 +59,10 @@ public: void CalculateTrapHandlerSymbolNames() override; - uint64_t ConvertMmapFlagsToPlatform(const ArchSpec &arch, - unsigned flags) override; + MmapArgList GetMmapArgumentList(const ArchSpec &arch, lldb::addr_t addr, + lldb::addr_t length, unsigned prot, + unsigned flags, lldb::addr_t fd, + lldb::addr_t offset) override; private: DISALLOW_COPY_AND_ASSIGN(PlatformLinux); diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp index 0197d27e76ef7..a216e3839dd9c 100644 --- a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp @@ -206,7 +206,7 @@ lldb::ProcessSP PlatformAppleSimulator::DebugProcess( // open for stdin/out/err after we have already opened the master // so we can read/write stdin/out/err. int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); - if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd) { + if (pty_fd != PseudoTerminal::invalid_fd) { process_sp->SetSTDIOFileDescriptor(pty_fd); } } diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp index 52188eefb3661..e0558f8b200e7 100644 --- a/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp @@ -14,7 +14,6 @@ // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" @@ -23,6 +22,7 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp index b9f493294a037..9b2608f68625c 100644 --- a/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp @@ -14,7 +14,6 @@ // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" @@ -23,6 +22,7 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp index f87852ed7f440..b39aa103f1dbd 100644 --- a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -1132,28 +1132,33 @@ bool PlatformDarwin::ARMGetSupportedArchitectureAtIndex(uint32_t idx, return false; } +// Return a directory path like /Applications/Xcode.app/Contents/Developer const char *PlatformDarwin::GetDeveloperDirectory() { std::lock_guard<std::mutex> guard(m_mutex); if (m_developer_directory.empty()) { bool developer_dir_path_valid = false; char developer_dir_path[PATH_MAX]; FileSpec temp_file_spec; + + // Get the lldb framework's file path, and if it exists, truncate some + // components to only the developer directory path. if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, temp_file_spec)) { if (temp_file_spec.GetPath(developer_dir_path, sizeof(developer_dir_path))) { + // e.g. /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework char *shared_frameworks = strstr(developer_dir_path, "/SharedFrameworks/LLDB.framework"); if (shared_frameworks) { - ::snprintf(shared_frameworks, - sizeof(developer_dir_path) - - (shared_frameworks - developer_dir_path), - "/Developer"); + shared_frameworks[0] = '\0'; // truncate developer_dir_path at this point + strncat (developer_dir_path, "/Developer", sizeof (developer_dir_path) - 1); // add /Developer on developer_dir_path_valid = true; } else { - char *lib_priv_frameworks = strstr( - developer_dir_path, "/Library/PrivateFrameworks/LLDB.framework"); - if (lib_priv_frameworks) { - *lib_priv_frameworks = '\0'; + // e.g. /Applications/Xcode.app/Contents/Developer/Toolchains/iOS11.2.xctoolchain/System/Library/PrivateFrameworks/LLDB.framework + char *developer_toolchains = + strstr(developer_dir_path, "/Contents/Developer/Toolchains/"); + if (developer_toolchains) { + developer_toolchains += sizeof ("/Contents/Developer") - 1; + developer_toolchains[0] = '\0'; // truncate developer_dir_path at this point developer_dir_path_valid = true; } } diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp index f168fb6fda5e8..e5d27fc289496 100644 --- a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp @@ -18,7 +18,6 @@ // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" @@ -31,6 +30,7 @@ #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" @@ -694,7 +694,16 @@ Status PlatformDarwinKernel::GetSharedModule( } } - // Second look through the kext binarys without dSYMs + // Give the generic methods, including possibly calling into + // DebugSymbols framework on macOS systems, a chance. + error = PlatformDarwin::GetSharedModule(module_spec, process, module_sp, + module_search_paths_ptr, + old_module_sp_ptr, did_create_ptr); + if (error.Success() && module_sp.get()) { + return error; + } + + // Lastly, look through the kext binarys without dSYMs if (m_name_to_kext_path_map_without_dsyms.count(kext_bundle_cs) > 0) { for (BundleIDToKextIterator it = m_name_to_kext_path_map_without_dsyms.begin(); @@ -739,7 +748,17 @@ Status PlatformDarwinKernel::GetSharedModule( } } } - // Second try all kernel binaries that don't have a dSYM + + // Give the generic methods, including possibly calling into + // DebugSymbols framework on macOS systems, a chance. + error = PlatformDarwin::GetSharedModule(module_spec, process, module_sp, + module_search_paths_ptr, + old_module_sp_ptr, did_create_ptr); + if (error.Success() && module_sp.get()) { + return error; + } + + // Next try all kernel binaries that don't have a dSYM for (auto possible_kernel : m_kernel_binaries_without_dsyms) { if (possible_kernel.Exists()) { ModuleSpec kern_spec(possible_kernel); @@ -767,11 +786,7 @@ Status PlatformDarwinKernel::GetSharedModule( } } - // Else fall back to treating the file's path as an actual file path - defer - // to PlatformDarwin's GetSharedModule. - return PlatformDarwin::GetSharedModule(module_spec, process, module_sp, - module_search_paths_ptr, - old_module_sp_ptr, did_create_ptr); + return error; } Status PlatformDarwinKernel::ExamineKextForMatchingUUID( diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp index 38facc4aa124c..1eef643d39046 100644 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp @@ -17,7 +17,6 @@ #include "PlatformRemoteAppleTV.h" #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" @@ -25,6 +24,7 @@ #include "lldb/Host/Host.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp index bbd8f16989370..17ae67bc28deb 100644 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp @@ -17,7 +17,6 @@ #include "PlatformRemoteAppleWatch.h" #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" @@ -25,6 +24,7 @@ #include "lldb/Host/Host.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp index ea44714a916e4..cb064aad6155b 100644 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp @@ -14,7 +14,6 @@ // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp index c52b636c8496f..5bff792525bcc 100644 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp @@ -14,7 +14,6 @@ // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" @@ -22,6 +21,7 @@ #include "lldb/Host/Host.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp index 3037dd854be70..ee1f90311e7ea 100644 --- a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp @@ -15,7 +15,6 @@ // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" @@ -24,6 +23,7 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm b/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm index 6a49b645c1e17..7bd37683d2fd4 100644 --- a/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm +++ b/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm @@ -22,7 +22,6 @@ #include "llvm/ADT/StringRef.h" using namespace lldb_private; -using namespace lldb_utility; // CoreSimulator lives as part of Xcode, which means we can't really link // against it, so we dlopen() // it at runtime, and error out nicely if that fails diff --git a/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp b/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp index 9df5b9fac3805..38bdf60c1ced6 100644 --- a/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp +++ b/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp @@ -393,7 +393,7 @@ lldb::ProcessSP PlatformNetBSD::DebugProcess( // Hook up process PTY if we have one (which we should for local debugging // with llgs). int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); - if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd) { + if (pty_fd != PseudoTerminal::invalid_fd) { process_sp->SetSTDIOFileDescriptor(pty_fd); if (log) log->Printf("PlatformNetBSD::%s pid %" PRIu64 @@ -420,13 +420,17 @@ void PlatformNetBSD::CalculateTrapHandlerSymbolNames() { m_trap_handlers.push_back(ConstString("_sigtramp")); } -uint64_t PlatformNetBSD::ConvertMmapFlagsToPlatform(const ArchSpec &arch, - unsigned flags) { +MmapArgList PlatformNetBSD::GetMmapArgumentList(const ArchSpec &arch, + addr_t addr, addr_t length, + unsigned prot, unsigned flags, + addr_t fd, addr_t offset) { uint64_t flags_platform = 0; if (flags & eMmapFlagsPrivate) flags_platform |= MAP_PRIVATE; if (flags & eMmapFlagsAnon) flags_platform |= MAP_ANON; - return flags_platform; + + MmapArgList args({addr, length, prot, flags_platform, fd, offset}); + return args; } diff --git a/source/Plugins/Platform/NetBSD/PlatformNetBSD.h b/source/Plugins/Platform/NetBSD/PlatformNetBSD.h index b1aaa4ab5f59c..28a5d6713dd95 100644 --- a/source/Plugins/Platform/NetBSD/PlatformNetBSD.h +++ b/source/Plugins/Platform/NetBSD/PlatformNetBSD.h @@ -59,8 +59,10 @@ public: void CalculateTrapHandlerSymbolNames() override; - uint64_t ConvertMmapFlagsToPlatform(const ArchSpec &arch, - unsigned flags) override; + MmapArgList GetMmapArgumentList(const ArchSpec &arch, lldb::addr_t addr, + lldb::addr_t length, unsigned prot, + unsigned flags, lldb::addr_t fd, + lldb::addr_t offset) override; private: DISALLOW_COPY_AND_ASSIGN(PlatformNetBSD); diff --git a/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp b/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp index edb8ec951d374..050639aba7cc5 100644 --- a/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp +++ b/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp @@ -133,7 +133,7 @@ PlatformOpenBSD::PlatformOpenBSD(bool is_host) PlatformOpenBSD::~PlatformOpenBSD() = default; bool PlatformOpenBSD::GetSupportedArchitectureAtIndex(uint32_t idx, - ArchSpec &arch) { + ArchSpec &arch) { if (IsHost()) { ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); if (hostArch.GetTriple().isOSOpenBSD()) { @@ -211,13 +211,17 @@ void PlatformOpenBSD::CalculateTrapHandlerSymbolNames() { m_trap_handlers.push_back(ConstString("_sigtramp")); } -uint64_t PlatformOpenBSD::ConvertMmapFlagsToPlatform(const ArchSpec &arch, - unsigned flags) { +MmapArgList PlatformOpenBSD::GetMmapArgumentList(const ArchSpec &arch, + addr_t addr, addr_t length, + unsigned prot, unsigned flags, + addr_t fd, addr_t offset) { uint64_t flags_platform = 0; if (flags & eMmapFlagsPrivate) flags_platform |= MAP_PRIVATE; if (flags & eMmapFlagsAnon) flags_platform |= MAP_ANON; - return flags_platform; + + MmapArgList args({addr, length, prot, flags_platform, fd, offset}); + return args; } diff --git a/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.h b/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.h index 55f6451e236ef..cb5e9bfe63926 100644 --- a/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.h +++ b/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.h @@ -53,8 +53,10 @@ public: void CalculateTrapHandlerSymbolNames() override; - uint64_t ConvertMmapFlagsToPlatform(const ArchSpec &arch, - unsigned flags) override; + MmapArgList GetMmapArgumentList(const ArchSpec &arch, lldb::addr_t addr, + lldb::addr_t length, unsigned prot, + unsigned flags, lldb::addr_t fd, + lldb::addr_t offset) override; private: DISALLOW_COPY_AND_ASSIGN(PlatformOpenBSD); diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp index 013c33def13b9..d45a54ee24994 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -944,7 +944,7 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process, the_result; )", path); - llvm::StringRef prefix = GetLibdlFunctionDeclarations(); + llvm::StringRef prefix = GetLibdlFunctionDeclarations(process); lldb::ValueObjectSP result_valobj_sp; error = EvaluateLibdlExpression(process, expr.GetData(), prefix, result_valobj_sp); @@ -992,7 +992,7 @@ Status PlatformPOSIX::UnloadImage(lldb_private::Process *process, StreamString expr; expr.Printf("dlclose((void *)0x%" PRIx64 ")", image_addr); - llvm::StringRef prefix = GetLibdlFunctionDeclarations(); + llvm::StringRef prefix = GetLibdlFunctionDeclarations(process); lldb::ValueObjectSP result_valobj_sp; Status error = EvaluateLibdlExpression(process, expr.GetData(), prefix, result_valobj_sp); @@ -1024,7 +1024,8 @@ lldb::ProcessSP PlatformPOSIX::ConnectProcess(llvm::StringRef connect_url, error); } -llvm::StringRef PlatformPOSIX::GetLibdlFunctionDeclarations() { +llvm::StringRef +PlatformPOSIX::GetLibdlFunctionDeclarations(lldb_private::Process *process) { return R"( extern "C" void* dlopen(const char*, int); extern "C" void* dlsym(void*, const char*); diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h index ebc36c2461db1..93bebeb332cac 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.h +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h @@ -201,7 +201,8 @@ protected: llvm::StringRef expr_prefix, lldb::ValueObjectSP &result_valobj_sp); - virtual llvm::StringRef GetLibdlFunctionDeclarations(); + virtual + llvm::StringRef GetLibdlFunctionDeclarations(lldb_private::Process *process); private: DISALLOW_COPY_AND_ASSIGN(PlatformPOSIX); diff --git a/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp b/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp index c6daf6ccea6e3..6b3d5f6c117fe 100644 --- a/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp +++ b/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp @@ -144,7 +144,7 @@ static Status ForkChildForPTraceDebugging(const char *path, char const *argv[], // Use a fork that ties the child process's stdin/out/err to a pseudo // terminal so we can read it in our MachProcess::STDIOThread // as unbuffered io. - lldb_utility::PseudoTerminal pty; + PseudoTerminal pty; char fork_error[256]; memset(fork_error, 0, sizeof(fork_error)); *pid = static_cast<::pid_t>(pty.Fork(fork_error, sizeof(fork_error))); diff --git a/source/Plugins/Process/Darwin/MachException.cpp b/source/Plugins/Process/Darwin/MachException.cpp index 7d956dfc65060..9f5920753d68d 100644 --- a/source/Plugins/Process/Darwin/MachException.cpp +++ b/source/Plugins/Process/Darwin/MachException.cpp @@ -57,11 +57,6 @@ extern "C" kern_return_t catch_mach_exception_raise_state_identity( extern "C" boolean_t mach_exc_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); -// Any access to the g_message variable should be done by locking the -// g_message_mutex first, using the g_message variable, then unlocking -// the g_message_mutex. See MachException::Message::CatchExceptionRaise() -// for sample code. - static MachException::Data *g_message = NULL; extern "C" kern_return_t catch_mach_exception_raise_state( @@ -131,33 +126,6 @@ catch_mach_exception_raise(mach_port_t exc_port, mach_port_t thread_port, return KERN_FAILURE; } -#if 0 -void -MachException::Message::Dump(Stream &stream) const -{ - stream.Printf("exc_msg { bits = 0x%8.8x size = 0x%8.8x remote-port = " - "0x%8.8x local-port = 0x%8.8x reserved = 0x%8.8x " - "id = 0x%8.8x }\n", - exc_msg.hdr.msgh_bits, - exc_msg.hdr.msgh_size, - exc_msg.hdr.msgh_remote_port, - exc_msg.hdr.msgh_local_port, - exc_msg.hdr.msgh_reserved, - exc_msg.hdr.msgh_id); - - stream.Printf("reply_msg { bits = 0x%8.8x size = 0x%8.8x remote-port " - "= 0x%8.8x local-port = 0x%8.8x reserved = 0x%8.8x " - "id = 0x%8.8x }", - reply_msg.hdr.msgh_bits, - reply_msg.hdr.msgh_size, - reply_msg.hdr.msgh_remote_port, - reply_msg.hdr.msgh_local_port, - reply_msg.hdr.msgh_reserved, - reply_msg.hdr.msgh_id); - stream.Flush(); -} -#endif - bool MachException::Data::GetStopInfo(struct ThreadStopInfo *stop_info, const UnixSignals &signals, Stream &stream) const { @@ -279,9 +247,6 @@ void MachException::Message::Dump(Stream &stream) const { bool MachException::Message::CatchExceptionRaise(task_t task) { bool success = false; - // locker will keep a mutex locked until it goes out of scope - // PThreadMutex::Locker locker(&g_message_mutex); - // DNBLogThreaded("calling mach_exc_server"); state.task_port = task; g_message = &state; // The exc_server function is the MIG generated server handling function diff --git a/source/Plugins/Process/Darwin/NativeProcessDarwin.h b/source/Plugins/Process/Darwin/NativeProcessDarwin.h index 2214bbc52ca45..649280c17a8f3 100644 --- a/source/Plugins/Process/Darwin/NativeProcessDarwin.h +++ b/source/Plugins/Process/Darwin/NativeProcessDarwin.h @@ -22,12 +22,12 @@ #include <unordered_set> // Other libraries and framework includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Host/Debug.h" #include "lldb/Host/HostThread.h" #include "lldb/Host/Pipe.h" #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/FileSpec.h" #include "lldb/lldb-types.h" @@ -197,20 +197,6 @@ private: // waitpid reader callback handle. MainLoop::ReadHandleUP m_waitpid_reader_handle; -#if 0 - ArchSpec m_arch; - - LazyBool m_supports_mem_region; - std::vector<MemoryRegionInfo> m_mem_region_cache; - - lldb::tid_t m_pending_notification_tid; - - // List of thread ids stepping with a breakpoint with the address of - // the relevan breakpoint - std::map<lldb::tid_t, lldb::addr_t> - m_threads_stepping_with_breakpoint; -#endif - // ----------------------------------------------------------------- // Private Instance Methods // ----------------------------------------------------------------- @@ -322,20 +308,6 @@ private: Status SetupSoftwareSingleStepping(NativeThreadDarwin &thread); -#if 0 - 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); -#endif - bool HasThreadNoLock(lldb::tid_t thread_id); bool StopTrackingThread(lldb::tid_t thread_id); diff --git a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp index bd8e5abe2255f..e6557c2d58e03 100644 --- a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp +++ b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp @@ -375,6 +375,7 @@ void FreeBSDThread::Notify(const ProcessMessage &message) { LimboNotify(message); break; + case ProcessMessage::eCrashMessage: case ProcessMessage::eSignalMessage: SignalNotify(message); break; @@ -395,10 +396,6 @@ void FreeBSDThread::Notify(const ProcessMessage &message) { WatchNotify(message); break; - case ProcessMessage::eCrashMessage: - CrashNotify(message); - break; - case ProcessMessage::eExecMessage: ExecNotify(message); break; @@ -577,7 +574,14 @@ void FreeBSDThread::LimboNotify(const ProcessMessage &message) { void FreeBSDThread::SignalNotify(const ProcessMessage &message) { int signo = message.GetSignal(); - SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, signo)); + if (message.GetKind() == ProcessMessage::eCrashMessage) { + std::string stop_description = GetCrashReasonString( + message.GetCrashReason(), message.GetFaultAddress()); + SetStopInfo(StopInfo::CreateStopReasonWithSignal( + *this, signo, stop_description.c_str())); + } else { + SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, signo)); + } } void FreeBSDThread::SignalDeliveredNotify(const ProcessMessage &message) { @@ -585,21 +589,6 @@ void FreeBSDThread::SignalDeliveredNotify(const ProcessMessage &message) { SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, signo)); } -void FreeBSDThread::CrashNotify(const ProcessMessage &message) { - // FIXME: Update stop reason as per bugzilla 14598 - int signo = message.GetSignal(); - - assert(message.GetKind() == ProcessMessage::eCrashMessage); - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - if (log) - log->Printf("FreeBSDThread::%s () signo = %i, reason = '%s'", __FUNCTION__, - signo, message.PrintCrashReason()); - - SetStopInfo(lldb::StopInfoSP(new POSIXCrashStopInfo( - *this, signo, message.GetCrashReason(), message.GetFaultAddress()))); -} - unsigned FreeBSDThread::GetRegisterIndexFromOffset(unsigned offset) { unsigned reg = LLDB_INVALID_REGNUM; ArchSpec arch = HostInfo::GetArchitecture(); diff --git a/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp b/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp index dfbd695899ffb..9c75c26e379b5 100644 --- a/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp +++ b/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp @@ -28,22 +28,6 @@ bool POSIXLimboStopInfo::ShouldStop(Event *event_ptr) { return false; } bool POSIXLimboStopInfo::ShouldNotify(Event *event_ptr) { return false; } //===----------------------------------------------------------------------===// -// POSIXCrashStopInfo - -POSIXCrashStopInfo::POSIXCrashStopInfo(FreeBSDThread &thread, uint32_t status, - CrashReason reason, - lldb::addr_t fault_addr) - : POSIXStopInfo(thread, status) { - m_description = ::GetCrashReasonString(reason, fault_addr); -} - -POSIXCrashStopInfo::~POSIXCrashStopInfo() {} - -lldb::StopReason POSIXCrashStopInfo::GetStopReason() const { - return lldb::eStopReasonException; -} - -//===----------------------------------------------------------------------===// // POSIXNewThreadStopInfo POSIXNewThreadStopInfo::~POSIXNewThreadStopInfo() {} diff --git a/source/Plugins/Process/FreeBSD/POSIXStopInfo.h b/source/Plugins/Process/FreeBSD/POSIXStopInfo.h index e51fc08d74cc7..96861852b38eb 100644 --- a/source/Plugins/Process/FreeBSD/POSIXStopInfo.h +++ b/source/Plugins/Process/FreeBSD/POSIXStopInfo.h @@ -45,19 +45,6 @@ public: }; //===----------------------------------------------------------------------===// -/// @class POSIXCrashStopInfo -/// @brief Represents the stop state of process that is ready to crash. -/// -class POSIXCrashStopInfo : public POSIXStopInfo { -public: - POSIXCrashStopInfo(FreeBSDThread &thread, uint32_t status, CrashReason reason, - lldb::addr_t fault_addr); - ~POSIXCrashStopInfo(); - - lldb::StopReason GetStopReason() const; -}; - -//===----------------------------------------------------------------------===// /// @class POSIXNewThreadStopInfo /// @brief Represents the stop state of process when a new thread is spawned. /// diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp index 3046150e3246a..7a937db49be0c 100644 --- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp @@ -825,32 +825,6 @@ uint32_t ProcessFreeBSD::UpdateThreadListIfNeeded() { return m_thread_list.GetSize(false); } -#if 0 -bool -ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf ("ProcessFreeBSD::%s() (pid = %" PRIi64 ")", __FUNCTION__, GetID()); - - bool has_updated = false; - // Update the process thread list with this new thread. - // FIXME: We should be using tid, not pid. - assert(m_monitor); - ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false)); - if (!thread_sp) { - thread_sp.reset(CreateNewFreeBSDThread(*this, GetID())); - has_updated = true; - } - - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf ("ProcessFreeBSD::%s() updated pid = %" PRIi64, __FUNCTION__, GetID()); - new_thread_list.AddThread(thread_sp); - - return has_updated; // the list has been updated -} -#endif - ByteOrder ProcessFreeBSD::GetByteOrder() const { // FIXME: We should be able to extract this value directly. See comment in // ProcessFreeBSD(). diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp index a4f5f02dde62e..bd06fa25f0a01 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -843,7 +843,7 @@ bool ProcessMonitor::Launch(LaunchArgs *args) { const FileSpec &stderr_file_spec = args->m_stderr_file_spec; const FileSpec &working_dir = args->m_working_dir; - lldb_utility::PseudoTerminal terminal; + PseudoTerminal terminal; const size_t err_len = 1024; char err_str[err_len]; ::pid_t pid; @@ -1192,7 +1192,9 @@ ProcessMessage ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, case SIGBUS: lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr); const auto reason = GetCrashReason(*info); - return ProcessMessage::Crash(tid, reason, signo, fault_addr); + if (reason != CrashReason::eInvalidCrashReason) { + return ProcessMessage::Crash(tid, reason, signo, fault_addr); + } // else; Use atleast si_signo info for other si_code } // Everything else is "normal" and does not require any special action on diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h b/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h index c0b9b2f4a2d3c..4ff5121bac130 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h @@ -14,8 +14,8 @@ // C++ Includes // Other libraries and framework includes #include "RegisterInfoInterface.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/ArchSpec.h" //------------------------------------------------------------------------------ /// @class POSIXBreakpointProtocol diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp index 1cd8f1aafa6e3..4608520dba409 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp @@ -58,6 +58,9 @@ RegisterContextPOSIXProcessMonitor_x86_64:: // Store byte offset of fctrl (i.e. first register of FPR) wrt 'UserArea' const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl"); m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset; + + m_iovec.iov_base = &m_fpr.xsave; + m_iovec.iov_len = sizeof(m_fpr.xsave); } ProcessMonitor &RegisterContextPOSIXProcessMonitor_x86_64::GetMonitor() { @@ -74,12 +77,12 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::ReadGPR() { bool RegisterContextPOSIXProcessMonitor_x86_64::ReadFPR() { ProcessMonitor &monitor = GetMonitor(); if (GetFPRType() == eFXSAVE) - return monitor.ReadFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, - sizeof(m_fpr.xstate.fxsave)); + return monitor.ReadFPR(m_thread.GetID(), &m_fpr.fxsave, + sizeof(m_fpr.fxsave)); if (GetFPRType() == eXSAVE) return monitor.ReadRegisterSet(m_thread.GetID(), &m_iovec, - sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); + sizeof(m_fpr.xsave), NT_X86_XSTATE); return false; } @@ -91,12 +94,12 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::WriteGPR() { bool RegisterContextPOSIXProcessMonitor_x86_64::WriteFPR() { ProcessMonitor &monitor = GetMonitor(); if (GetFPRType() == eFXSAVE) - return monitor.WriteFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, - sizeof(m_fpr.xstate.fxsave)); + return monitor.WriteFPR(m_thread.GetID(), &m_fpr.fxsave, + sizeof(m_fpr.fxsave)); if (GetFPRType() == eXSAVE) return monitor.WriteRegisterSet(m_thread.GetID(), &m_iovec, - sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); + sizeof(m_fpr.xsave), NT_X86_XSTATE); return false; } @@ -209,17 +212,14 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister( if (byte_order != ByteOrder::eByteOrderInvalid) { if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st) - value.SetBytes( - m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, - reg_info->byte_size, byte_order); + value.SetBytes(m_fpr.fxsave.stmm[reg - m_reg_info.first_st].bytes, + reg_info->byte_size, byte_order); if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm) - value.SetBytes( - m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, - reg_info->byte_size, byte_order); + value.SetBytes(m_fpr.fxsave.stmm[reg - m_reg_info.first_mm].bytes, + reg_info->byte_size, byte_order); if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm) - value.SetBytes( - m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, - reg_info->byte_size, byte_order); + value.SetBytes(m_fpr.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, + reg_info->byte_size, byte_order); if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) { // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes if (GetFPRType() == eXSAVE && CopyXSTATEtoYMM(reg, byte_order)) @@ -233,7 +233,7 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister( return false; } - // Get pointer to m_fpr.xstate.fxsave variable and set the data from it. + // Get pointer to m_fpr.fxsave variable and set the data from it. // Byte offsets of all registers are calculated wrt 'UserArea' structure. // However, ReadFPR() reads fpu registers {using ptrace(PT_GETFPREGS,..)} // and stores them in 'm_fpr' (of type FPR structure). To extract values of @@ -276,15 +276,15 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister( if (IsFPR(reg, GetFPRType())) { if (reg_info->encoding == eEncodingVector) { if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st) - ::memcpy(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, + ::memcpy(m_fpr.fxsave.stmm[reg - m_reg_info.first_st].bytes, value.GetBytes(), value.GetByteSize()); if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm) - ::memcpy(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, + ::memcpy(m_fpr.fxsave.stmm[reg - m_reg_info.first_mm].bytes, value.GetBytes(), value.GetByteSize()); if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm) - ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, + ::memcpy(m_fpr.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, value.GetBytes(), value.GetByteSize()); if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) { @@ -299,7 +299,7 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister( return false; } } else { - // Get pointer to m_fpr.xstate.fxsave variable and set the data to it. + // Get pointer to m_fpr.fxsave variable and set the data to it. // Byte offsets of all registers are calculated wrt 'UserArea' structure. // However, WriteFPR() takes m_fpr (of type FPR structure) and writes only // fpu @@ -353,7 +353,7 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::ReadAllRegisterValues( ::memcpy(dst, &m_gpr_x86_64, GetGPRSize()); dst += GetGPRSize(); if (GetFPRType() == eFXSAVE) - ::memcpy(dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave)); + ::memcpy(dst, &m_fpr.fxsave, sizeof(m_fpr.fxsave)); } if (GetFPRType() == eXSAVE) { @@ -385,9 +385,9 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::WriteAllRegisterValues( if (WriteGPR()) { src += GetGPRSize(); if (GetFPRType() == eFXSAVE) - ::memcpy(&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave)); + ::memcpy(&m_fpr.fxsave, src, sizeof(m_fpr.fxsave)); if (GetFPRType() == eXSAVE) - ::memcpy(&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave)); + ::memcpy(&m_fpr.xsave, src, sizeof(m_fpr.xsave)); success = WriteFPR(); if (success) { diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h index 57e2d00e668fd..8c654f97dcd9f 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h @@ -12,6 +12,7 @@ #include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h" #include "RegisterContextPOSIX.h" +#include <sys/uio.h> class RegisterContextPOSIXProcessMonitor_x86_64 : public RegisterContextPOSIX_x86, @@ -75,6 +76,7 @@ private: ProcessMonitor &GetMonitor(); uint32_t m_fctrl_offset_in_userarea; // Offset of 'fctrl' in 'UserArea' Structure + struct iovec m_iovec; }; #endif diff --git a/source/Plugins/Process/Linux/CMakeLists.txt b/source/Plugins/Process/Linux/CMakeLists.txt index 8330cac160e6a..390dbd9ff8bf6 100644 --- a/source/Plugins/Process/Linux/CMakeLists.txt +++ b/source/Plugins/Process/Linux/CMakeLists.txt @@ -7,9 +7,10 @@ add_lldb_library(lldbPluginProcessLinux PLUGIN NativeRegisterContextLinux.cpp NativeRegisterContextLinux_arm.cpp NativeRegisterContextLinux_arm64.cpp - NativeRegisterContextLinux_x86_64.cpp NativeRegisterContextLinux_mips64.cpp + NativeRegisterContextLinux_ppc64le.cpp NativeRegisterContextLinux_s390x.cpp + NativeRegisterContextLinux_x86_64.cpp NativeThreadLinux.cpp ProcessorTrace.cpp SingleStepCheck.cpp diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/source/Plugins/Process/Linux/NativeProcessLinux.cpp index 170d3b1000641..136af361af296 100644 --- a/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -177,7 +177,7 @@ void PtraceDisplayBytes(int &req, void *data, size_t data_size) { break; } case PTRACE_SETREGSET: { - // Extract iov_base from data, which is a pointer to the struct IOVEC + // Extract iov_base from data, which is a pointer to the struct iovec DisplayBytes(buf, *(void **)data, data_size); LLDB_LOGV(log, "PTRACE_SETREGSET {0}", buf.GetData()); break; @@ -305,10 +305,9 @@ NativeProcessLinux::NativeProcessLinux(::pid_t pid, int terminal_fd, assert(m_sigchld_handle && status.Success()); for (const auto &tid : tids) { - NativeThreadLinuxSP thread_sp = AddThread(tid); - assert(thread_sp && "AddThread() returned a nullptr thread"); - thread_sp->SetStoppedBySignal(SIGSTOP); - ThreadWasCreated(*thread_sp); + NativeThreadLinux &thread = AddThread(tid); + thread.SetStoppedBySignal(SIGSTOP); + ThreadWasCreated(thread); } // Let our process instance know the thread has stopped. @@ -413,46 +412,20 @@ void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited, // Handle when the thread exits. if (exited) { - LLDB_LOG(log, "got exit signal({0}) , tid = {1} ({2} main thread)", signal, - pid, is_main_thread ? "is" : "is not"); + LLDB_LOG(log, + "got exit signal({0}) , tid = {1} ({2} main thread), process " + "state = {3}", + signal, pid, is_main_thread ? "is" : "is not", GetState()); // This is a thread that exited. Ensure we're not tracking it anymore. - const bool thread_found = StopTrackingThread(pid); + StopTrackingThread(pid); if (is_main_thread) { - // We only set the exit status and notify the delegate if we haven't - // already set the process - // state to an exited state. We normally should have received a SIGTRAP | - // (PTRACE_EVENT_EXIT << 8) - // for the main thread. - const bool already_notified = (GetState() == StateType::eStateExited) || - (GetState() == StateType::eStateCrashed); - if (!already_notified) { - LLDB_LOG( - log, - "tid = {0} handling main thread exit ({1}), expected exit state " - "already set but state was {2} instead, setting exit state now", - pid, - thread_found ? "stopped tracking thread metadata" - : "thread metadata not found", - GetState()); - // The main thread exited. We're done monitoring. Report to delegate. - SetExitStatus(status, true); + // The main thread exited. We're done monitoring. Report to delegate. + SetExitStatus(status, true); - // Notify delegate that our process has exited. - SetState(StateType::eStateExited, true); - } else - LLDB_LOG(log, "tid = {0} main thread now exited (%s)", pid, - thread_found ? "stopped tracking thread metadata" - : "thread metadata not found"); - } else { - // Do we want to report to the delegate in this case? I think not. If - // this was an orderly thread exit, we would already have received the - // SIGTRAP | (PTRACE_EVENT_EXIT << 8) signal, and we would have done an - // all-stop then. - LLDB_LOG(log, "tid = {0} handling non-main thread exit (%s)", pid, - thread_found ? "stopped tracking thread metadata" - : "thread metadata not found"); + // Notify delegate that our process has exited. + SetState(StateType::eStateExited, true); } return; } @@ -478,11 +451,11 @@ void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited, LLDB_LOG(log, "tid {0}, si_code: {1}, si_pid: {2}", pid, info.si_code, info.si_pid); - auto thread_sp = AddThread(pid); + NativeThreadLinux &thread = AddThread(pid); // Resume the newly created thread. - ResumeThread(*thread_sp, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); - ThreadWasCreated(*thread_sp); + ResumeThread(thread, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); + ThreadWasCreated(thread); return; } @@ -549,12 +522,9 @@ void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited, void NativeProcessLinux::WaitForNewThread(::pid_t tid) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - NativeThreadLinuxSP new_thread_sp = GetThreadByID(tid); - - if (new_thread_sp) { + if (GetThreadByID(tid)) { // We are already tracking the thread - we got the event on the new thread - // (see - // MonitorSignal) before this one. We are done. + // (see MonitorSignal) before this one. We are done. return; } @@ -587,10 +557,10 @@ void NativeProcessLinux::WaitForNewThread(::pid_t tid) { } LLDB_LOG(log, "pid = {0}: tracking new thread tid {1}", GetID(), tid); - new_thread_sp = AddThread(tid); + NativeThreadLinux &new_thread = AddThread(tid); - ResumeThread(*new_thread_sp, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); - ThreadWasCreated(*new_thread_sp); + ResumeThread(new_thread, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); + ThreadWasCreated(new_thread); } void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, @@ -630,7 +600,6 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, } case (SIGTRAP | (PTRACE_EVENT_EXEC << 8)): { - NativeThreadLinuxSP main_thread_sp; LLDB_LOG(log, "received exec event, code = {0}", info.si_code ^ SIGTRAP); // Exec clears any pending notifications. @@ -640,44 +609,26 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, // which only copies the main thread. LLDB_LOG(log, "exec received, stop tracking all but main thread"); - for (auto thread_sp : m_threads) { - const bool is_main_thread = thread_sp && thread_sp->GetID() == GetID(); - if (is_main_thread) { - main_thread_sp = std::static_pointer_cast<NativeThreadLinux>(thread_sp); - LLDB_LOG(log, "found main thread with tid {0}, keeping", - main_thread_sp->GetID()); - } else { - LLDB_LOG(log, "discarding non-main-thread tid {0} due to exec", - thread_sp->GetID()); - } + for (auto i = m_threads.begin(); i != m_threads.end();) { + if ((*i)->GetID() == GetID()) + i = m_threads.erase(i); + else + ++i; } + assert(m_threads.size() == 1); + auto *main_thread = static_cast<NativeThreadLinux *>(m_threads[0].get()); - m_threads.clear(); - - if (main_thread_sp) { - m_threads.push_back(main_thread_sp); - SetCurrentThreadID(main_thread_sp->GetID()); - main_thread_sp->SetStoppedByExec(); - } else { - SetCurrentThreadID(LLDB_INVALID_THREAD_ID); - LLDB_LOG(log, - "pid {0} no main thread found, discarded all threads, " - "we're in a no-thread state!", - GetID()); - } + SetCurrentThreadID(main_thread->GetID()); + main_thread->SetStoppedByExec(); // Tell coordinator about about the "new" (since exec) stopped main thread. - ThreadWasCreated(*main_thread_sp); + ThreadWasCreated(*main_thread); // Let our delegate know we have just exec'd. NotifyDidExec(); - // If we have a main thread, indicate we are stopped. - assert(main_thread_sp && "exec called during ptraced process but no main " - "thread metadata tracked"); - // Let the process know we're stopped. - StopRunningThreads(main_thread_sp->GetID()); + StopRunningThreads(main_thread->GetID()); break; } @@ -685,10 +636,8 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, case (SIGTRAP | (PTRACE_EVENT_EXIT << 8)): { // The inferior process or one of its threads is about to exit. // We don't want to do anything with the thread so we just resume it. In - // case we - // want to implement "break on thread exit" functionality, we would need to - // stop - // here. + // case we want to implement "break on thread exit" functionality, we would + // need to stop here. unsigned long data = 0; if (GetEventMessage(thread.GetID(), &data).Fail()) @@ -700,18 +649,14 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, data, WIFEXITED(data), WIFSIGNALED(data), thread.GetID(), is_main_thread); - if (is_main_thread) - SetExitStatus(WaitStatus::Decode(data), true); StateType state = thread.GetState(); if (!StateIsRunningState(state)) { // Due to a kernel bug, we may sometimes get this stop after the inferior - // gets a - // SIGKILL. This confuses our state tracking logic in ResumeThread(), - // since normally, - // we should not be receiving any ptrace events while the inferior is - // stopped. This - // makes sure that the inferior is resumed and exits normally. + // gets a SIGKILL. This confuses our state tracking logic in + // ResumeThread(), since normally, we should not be receiving any ptrace + // events while the inferior is stopped. This makes sure that the inferior + // is resumed and exits normally. state = eStateRunning; } ResumeThread(thread, state, LLDB_INVALID_SIGNAL_NUMBER); @@ -725,7 +670,7 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, { // If a watchpoint was hit, report it uint32_t wp_index; - Status error = thread.GetRegisterContext()->GetWatchpointHitIndex( + Status error = thread.GetRegisterContext().GetWatchpointHitIndex( wp_index, (uintptr_t)info.si_addr); if (error.Fail()) LLDB_LOG(log, @@ -739,7 +684,7 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, // If a breakpoint was hit, report it uint32_t bp_index; - error = thread.GetRegisterContext()->GetHardwareBreakHitIndex( + error = thread.GetRegisterContext().GetHardwareBreakHitIndex( bp_index, (uintptr_t)info.si_addr); if (error.Fail()) LLDB_LOG(log, "received error while checking for hardware " @@ -762,7 +707,7 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, { // If a watchpoint was hit, report it uint32_t wp_index; - Status error = thread.GetRegisterContext()->GetWatchpointHitIndex( + Status error = thread.GetRegisterContext().GetWatchpointHitIndex( wp_index, LLDB_INVALID_ADDRESS); if (error.Fail()) LLDB_LOG(log, @@ -933,13 +878,13 @@ void NativeProcessLinux::MonitorSignal(const siginfo_t &info, namespace { struct EmulatorBaton { - NativeProcessLinux *m_process; - NativeRegisterContext *m_reg_context; + NativeProcessLinux &m_process; + NativeRegisterContext &m_reg_context; // eRegisterKindDWARF -> RegsiterValue std::unordered_map<uint32_t, RegisterValue> m_register_values; - EmulatorBaton(NativeProcessLinux *process, NativeRegisterContext *reg_context) + EmulatorBaton(NativeProcessLinux &process, NativeRegisterContext ®_context) : m_process(process), m_reg_context(reg_context) {} }; @@ -951,7 +896,7 @@ static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton, EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); size_t bytes_read; - emulator_baton->m_process->ReadMemory(addr, dst, length, bytes_read); + emulator_baton->m_process.ReadMemory(addr, dst, length, bytes_read); return bytes_read; } @@ -971,11 +916,11 @@ static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton, // the generic register numbers). Get the full register info from the // register context based on the dwarf register numbers. const RegisterInfo *full_reg_info = - emulator_baton->m_reg_context->GetRegisterInfo( + emulator_baton->m_reg_context.GetRegisterInfo( eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]); Status error = - emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value); + emulator_baton->m_reg_context.ReadRegister(full_reg_info, reg_value); if (error.Success()) return true; @@ -999,17 +944,17 @@ static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton, return length; } -static lldb::addr_t ReadFlags(NativeRegisterContext *regsiter_context) { - const RegisterInfo *flags_info = regsiter_context->GetRegisterInfo( +static lldb::addr_t ReadFlags(NativeRegisterContext ®siter_context) { + const RegisterInfo *flags_info = regsiter_context.GetRegisterInfo( eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); - return regsiter_context->ReadRegisterAsUnsigned(flags_info, - LLDB_INVALID_ADDRESS); + return regsiter_context.ReadRegisterAsUnsigned(flags_info, + LLDB_INVALID_ADDRESS); } Status NativeProcessLinux::SetupSoftwareSingleStepping(NativeThreadLinux &thread) { Status error; - NativeRegisterContextSP register_context_sp = thread.GetRegisterContext(); + NativeRegisterContext& register_context = thread.GetRegisterContext(); std::unique_ptr<EmulateInstruction> emulator_ap( EmulateInstruction::FindPlugin(m_arch, eInstructionTypePCModifying, @@ -1018,7 +963,7 @@ NativeProcessLinux::SetupSoftwareSingleStepping(NativeThreadLinux &thread) { if (emulator_ap == nullptr) return Status("Instruction emulator not found!"); - EmulatorBaton baton(this, register_context_sp.get()); + EmulatorBaton baton(*this, register_context); emulator_ap->SetBaton(&baton); emulator_ap->SetReadMemCallback(&ReadMemoryCallback); emulator_ap->SetReadRegCallback(&ReadRegisterCallback); @@ -1031,9 +976,9 @@ NativeProcessLinux::SetupSoftwareSingleStepping(NativeThreadLinux &thread) { bool emulation_result = emulator_ap->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC); - const RegisterInfo *reg_info_pc = register_context_sp->GetRegisterInfo( + const RegisterInfo *reg_info_pc = register_context.GetRegisterInfo( eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); - const RegisterInfo *reg_info_flags = register_context_sp->GetRegisterInfo( + const RegisterInfo *reg_info_flags = register_context.GetRegisterInfo( eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); auto pc_it = @@ -1051,15 +996,14 @@ NativeProcessLinux::SetupSoftwareSingleStepping(NativeThreadLinux &thread) { if (flags_it != baton.m_register_values.end()) next_flags = flags_it->second.GetAsUInt64(); else - next_flags = ReadFlags(register_context_sp.get()); + next_flags = ReadFlags(register_context); } else if (pc_it == baton.m_register_values.end()) { // Emulate instruction failed and it haven't changed PC. Advance PC // with the size of the current opcode because the emulation of all // PC modifying instruction should be successful. The failure most // likely caused by a not supported instruction which don't modify PC. - next_pc = - register_context_sp->GetPC() + emulator_ap->GetOpcode().GetByteSize(); - next_flags = ReadFlags(register_context_sp.get()); + next_pc = register_context.GetPC() + emulator_ap->GetOpcode().GetByteSize(); + next_flags = ReadFlags(register_context); } else { // The instruction emulation failed after it modified the PC. It is an // unknown error where we can't continue because the next instruction is @@ -1078,7 +1022,8 @@ NativeProcessLinux::SetupSoftwareSingleStepping(NativeThreadLinux &thread) { } else if (m_arch.GetMachine() == llvm::Triple::mips64 || m_arch.GetMachine() == llvm::Triple::mips64el || m_arch.GetMachine() == llvm::Triple::mips || - m_arch.GetMachine() == llvm::Triple::mipsel) + m_arch.GetMachine() == llvm::Triple::mipsel || + m_arch.GetMachine() == llvm::Triple::ppc64le) error = SetSoftwareBreakpoint(next_pc, 4); else { // No size hint is given for the next breakpoint @@ -1114,44 +1059,44 @@ Status NativeProcessLinux::Resume(const ResumeActionList &resume_actions) { bool software_single_step = !SupportHardwareSingleStepping(); if (software_single_step) { - for (auto thread_sp : m_threads) { - assert(thread_sp && "thread list should not contain NULL threads"); + for (const auto &thread : m_threads) { + assert(thread && "thread list should not contain NULL threads"); const ResumeAction *const action = - resume_actions.GetActionForThread(thread_sp->GetID(), true); + resume_actions.GetActionForThread(thread->GetID(), true); if (action == nullptr) continue; if (action->state == eStateStepping) { Status error = SetupSoftwareSingleStepping( - static_cast<NativeThreadLinux &>(*thread_sp)); + static_cast<NativeThreadLinux &>(*thread)); if (error.Fail()) return error; } } } - for (auto thread_sp : m_threads) { - assert(thread_sp && "thread list should not contain NULL threads"); + for (const auto &thread : m_threads) { + assert(thread && "thread list should not contain NULL threads"); const ResumeAction *const action = - resume_actions.GetActionForThread(thread_sp->GetID(), true); + resume_actions.GetActionForThread(thread->GetID(), true); if (action == nullptr) { LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(), - thread_sp->GetID()); + thread->GetID()); continue; } LLDB_LOG(log, "processing resume action state {0} for pid {1} tid {2}", - action->state, GetID(), thread_sp->GetID()); + action->state, GetID(), thread->GetID()); switch (action->state) { case eStateRunning: case eStateStepping: { // Run the thread, possibly feeding it the signal. const int signo = action->signal; - ResumeThread(static_cast<NativeThreadLinux &>(*thread_sp), action->state, + ResumeThread(static_cast<NativeThreadLinux &>(*thread), action->state, signo); break; } @@ -1164,7 +1109,7 @@ Status NativeProcessLinux::Resume(const ResumeActionList &resume_actions) { return Status("NativeProcessLinux::%s (): unexpected state %s specified " "for pid %" PRIu64 ", tid %" PRIu64, __FUNCTION__, StateAsCString(action->state), GetID(), - thread_sp->GetID()); + thread->GetID()); } } @@ -1190,8 +1135,8 @@ Status NativeProcessLinux::Detach() { if (GetID() == LLDB_INVALID_PROCESS_ID) return error; - for (auto thread_sp : m_threads) { - Status e = Detach(thread_sp->GetID()); + for (const auto &thread : m_threads) { + Status e = Detach(thread->GetID()); if (e.Fail()) error = e; // Save the error, but still attempt to detach from other threads. @@ -1221,29 +1166,25 @@ Status NativeProcessLinux::Interrupt() { // the chosen thread that will be the stop-reason thread. Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - NativeThreadProtocolSP running_thread_sp; - NativeThreadProtocolSP stopped_thread_sp; + NativeThreadProtocol *running_thread = nullptr; + NativeThreadProtocol *stopped_thread = nullptr; LLDB_LOG(log, "selecting running thread for interrupt target"); - for (auto thread_sp : m_threads) { - // The thread shouldn't be null but lets just cover that here. - if (!thread_sp) - continue; - + for (const auto &thread : m_threads) { // If we have a running or stepping thread, we'll call that the // target of the interrupt. - const auto thread_state = thread_sp->GetState(); + const auto thread_state = thread->GetState(); if (thread_state == eStateRunning || thread_state == eStateStepping) { - running_thread_sp = thread_sp; + running_thread = thread.get(); break; - } else if (!stopped_thread_sp && StateIsStoppedState(thread_state, true)) { + } else if (!stopped_thread && StateIsStoppedState(thread_state, true)) { // Remember the first non-dead stopped thread. We'll use that as a backup // if there are no running threads. - stopped_thread_sp = thread_sp; + stopped_thread = thread.get(); } } - if (!running_thread_sp && !stopped_thread_sp) { + if (!running_thread && !stopped_thread) { Status error("found no running/stepping or live stopped threads as target " "for interrupt"); LLDB_LOG(log, "skipping due to error: {0}", error); @@ -1251,14 +1192,14 @@ Status NativeProcessLinux::Interrupt() { return error; } - NativeThreadProtocolSP deferred_signal_thread_sp = - running_thread_sp ? running_thread_sp : stopped_thread_sp; + NativeThreadProtocol *deferred_signal_thread = + running_thread ? running_thread : stopped_thread; LLDB_LOG(log, "pid {0} {1} tid {2} chosen for interrupt target", GetID(), - running_thread_sp ? "running" : "stopped", - deferred_signal_thread_sp->GetID()); + running_thread ? "running" : "stopped", + deferred_signal_thread->GetID()); - StopRunningThreads(deferred_signal_thread_sp->GetID()); + StopRunningThreads(deferred_signal_thread->GetID()); return Status(); } @@ -1568,17 +1509,13 @@ size_t NativeProcessLinux::UpdateThreads() { return m_threads.size(); } -bool NativeProcessLinux::GetArchitecture(ArchSpec &arch) const { - arch = m_arch; - return true; -} - Status NativeProcessLinux::GetSoftwareBreakpointPCOffset( uint32_t &actual_opcode_size) { // FIXME put this behind a breakpoint protocol class that can be // set per architecture. Need ARM, MIPS support here. static const uint8_t g_i386_opcode[] = {0xCC}; static const uint8_t g_s390x_opcode[] = {0x00, 0x01}; + static const uint8_t g_ppc64le_opcode[] = {0x08, 0x00, 0xe0, 0x7f}; // trap switch (m_arch.GetMachine()) { case llvm::Triple::x86: @@ -1590,6 +1527,10 @@ Status NativeProcessLinux::GetSoftwareBreakpointPCOffset( actual_opcode_size = static_cast<uint32_t>(sizeof(g_s390x_opcode)); return Status(); + case llvm::Triple::ppc64le: + actual_opcode_size = static_cast<uint32_t>(sizeof(g_ppc64le_opcode)); + return Status(); + case llvm::Triple::arm: case llvm::Triple::aarch64: case llvm::Triple::mips64: @@ -1635,6 +1576,7 @@ Status NativeProcessLinux::GetSoftwareBreakpointTrapOpcode( static const uint8_t g_mips64el_opcode[] = {0x0d, 0x00, 0x00, 0x00}; static const uint8_t g_s390x_opcode[] = {0x00, 0x01}; static const uint8_t g_thumb_breakpoint_opcode[] = {0x01, 0xde}; + static const uint8_t g_ppc64le_opcode[] = {0x08, 0x00, 0xe0, 0x7f}; // trap switch (m_arch.GetMachine()) { case llvm::Triple::aarch64: @@ -1680,6 +1622,11 @@ Status NativeProcessLinux::GetSoftwareBreakpointTrapOpcode( actual_opcode_size = sizeof(g_s390x_opcode); return Status(); + case llvm::Triple::ppc64le: + trap_opcode_bytes = g_ppc64le_opcode; + actual_opcode_size = sizeof(g_ppc64le_opcode); + return Status(); + default: assert(false && "CPU type not supported!"); return Status("CPU type not supported"); @@ -1963,9 +1910,9 @@ Status NativeProcessLinux::Detach(lldb::tid_t tid) { } bool NativeProcessLinux::HasThreadNoLock(lldb::tid_t thread_id) { - for (auto thread_sp : m_threads) { - assert(thread_sp && "thread list should not contain NULL threads"); - if (thread_sp->GetID() == thread_id) { + for (const auto &thread : m_threads) { + assert(thread && "thread list should not contain NULL threads"); + if (thread->GetID() == thread_id) { // We have this thread. return true; } @@ -1994,7 +1941,7 @@ bool NativeProcessLinux::StopTrackingThread(lldb::tid_t thread_id) { return found; } -NativeThreadLinuxSP NativeProcessLinux::AddThread(lldb::tid_t thread_id) { +NativeThreadLinux &NativeProcessLinux::AddThread(lldb::tid_t thread_id) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id); @@ -2005,8 +1952,7 @@ NativeThreadLinuxSP NativeProcessLinux::AddThread(lldb::tid_t thread_id) { if (m_threads.empty()) SetCurrentThreadID(thread_id); - auto thread_sp = std::make_shared<NativeThreadLinux>(*this, thread_id); - m_threads.push_back(thread_sp); + m_threads.push_back(llvm::make_unique<NativeThreadLinux>(*this, thread_id)); if (m_pt_proces_trace_id != LLDB_INVALID_UID) { auto traceMonitor = ProcessorTraceMonitor::Create( @@ -2022,7 +1968,7 @@ NativeThreadLinuxSP NativeProcessLinux::AddThread(lldb::tid_t thread_id) { } } - return thread_sp; + return static_cast<NativeThreadLinux &>(*m_threads.back()); } Status @@ -2033,12 +1979,7 @@ NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) { // Find out the size of a breakpoint (might depend on where we are in the // code). - NativeRegisterContextSP context_sp = thread.GetRegisterContext(); - if (!context_sp) { - error.SetErrorString("cannot get a NativeRegisterContext for the thread"); - LLDB_LOG(log, "failed: {0}", error); - return error; - } + NativeRegisterContext &context = thread.GetRegisterContext(); uint32_t breakpoint_size = 0; error = GetSoftwareBreakpointPCOffset(breakpoint_size); @@ -2050,8 +1991,7 @@ NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) { // First try probing for a breakpoint at a software breakpoint location: PC - // breakpoint size. - const lldb::addr_t initial_pc_addr = - context_sp->GetPCfromBreakpointLocation(); + const lldb::addr_t initial_pc_addr = context.GetPCfromBreakpointLocation(); lldb::addr_t breakpoint_addr = initial_pc_addr; if (breakpoint_size > 0) { // Do not allow breakpoint probe to wrap around. @@ -2098,7 +2038,7 @@ NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) { LLDB_LOG(log, "pid {0} tid {1}: changing PC from {2:x} to {3:x}", GetID(), thread.GetID(), initial_pc_addr, breakpoint_addr); - error = context_sp->SetPC(breakpoint_addr); + error = context.SetPC(breakpoint_addr); if (error.Fail()) { LLDB_LOG(log, "pid {0} tid {1}: failed to set PC: {2}", GetID(), thread.GetID(), error); @@ -2144,8 +2084,8 @@ Status NativeProcessLinux::GetFileLoadAddress(const llvm::StringRef &file_name, return Status("No load address found for specified file."); } -NativeThreadLinuxSP NativeProcessLinux::GetThreadByID(lldb::tid_t tid) { - return std::static_pointer_cast<NativeThreadLinux>( +NativeThreadLinux *NativeProcessLinux::GetThreadByID(lldb::tid_t tid) { + return static_cast<NativeThreadLinux *>( NativeProcessProtocol::GetThreadByID(tid)); } @@ -2200,9 +2140,9 @@ void NativeProcessLinux::StopRunningThreads(const lldb::tid_t triggering_tid) { // Request a stop for all the thread stops that need to be stopped // and are not already known to be stopped. - for (const auto &thread_sp : m_threads) { - if (StateIsRunningState(thread_sp->GetState())) - static_pointer_cast<NativeThreadLinux>(thread_sp)->RequestStop(); + for (const auto &thread : m_threads) { + if (StateIsRunningState(thread->GetState())) + static_cast<NativeThreadLinux *>(thread.get())->RequestStop(); } SignalIfAllThreadsStopped(); diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.h b/source/Plugins/Process/Linux/NativeProcessLinux.h index c9ec002760f88..f078c1ac30e2a 100644 --- a/source/Plugins/Process/Linux/NativeProcessLinux.h +++ b/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -13,12 +13,11 @@ #include <csignal> #include <unordered_set> -// Other libraries and framework includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Host/Debug.h" #include "lldb/Host/HostThread.h" #include "lldb/Host/linux/Support.h" #include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/FileSpec.h" #include "lldb/lldb-types.h" @@ -87,7 +86,7 @@ public: size_t UpdateThreads() override; - bool GetArchitecture(ArchSpec &arch) const override; + const ArchSpec &GetArchitecture() const override { return m_arch; } Status SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) override; @@ -102,7 +101,7 @@ public: Status GetFileLoadAddress(const llvm::StringRef &file_name, lldb::addr_t &load_addr) override; - NativeThreadLinuxSP GetThreadByID(lldb::tid_t id); + NativeThreadLinux *GetThreadByID(lldb::tid_t id); llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> GetAuxvData() const override { @@ -203,7 +202,7 @@ private: bool StopTrackingThread(lldb::tid_t thread_id); - NativeThreadLinuxSP AddThread(lldb::tid_t thread_id); + NativeThreadLinux &AddThread(lldb::tid_t thread_id); Status GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size); diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp index 30f09f0c3a3f5..c8a8355f9cb99 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp @@ -14,27 +14,19 @@ #include "lldb/Host/common/NativeThreadProtocol.h" #include "lldb/Host/linux/Ptrace.h" +#include "Plugins/Process/Linux/NativeProcessLinux.h" #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" using namespace lldb_private; using namespace lldb_private::process_linux; NativeRegisterContextLinux::NativeRegisterContextLinux( - NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx, + NativeThreadProtocol &native_thread, RegisterInfoInterface *reg_info_interface_p) - : NativeRegisterContextRegisterInfo(native_thread, concrete_frame_idx, - reg_info_interface_p) {} + : NativeRegisterContextRegisterInfo(native_thread, reg_info_interface_p) {} lldb::ByteOrder NativeRegisterContextLinux::GetByteOrder() const { - // Get the target process whose privileged thread was used for the register - // read. - lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; - - if (!m_thread.GetProcess().GetByteOrder(byte_order)) { - // FIXME log here - } - - return byte_order; + return m_thread.GetProcess().GetByteOrder(); } Status NativeRegisterContextLinux::ReadRegisterRaw(uint32_t reg_index, diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux.h index 26074a6ce0e33..2cea497b53bcd 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux.h +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux.h @@ -10,10 +10,8 @@ #ifndef lldb_NativeRegisterContextLinux_h #define lldb_NativeRegisterContextLinux_h -#include "lldb/Host/common/NativeThreadProtocol.h" - -#include "Plugins/Process/Linux/NativeProcessLinux.h" #include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h" +#include "lldb/Host/common/NativeThreadProtocol.h" namespace lldb_private { namespace process_linux { @@ -21,20 +19,15 @@ namespace process_linux { class NativeRegisterContextLinux : public NativeRegisterContextRegisterInfo { public: NativeRegisterContextLinux(NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx, RegisterInfoInterface *reg_info_interface_p); // This function is implemented in the NativeRegisterContextLinux_* subclasses - // to create a new - // instance of the host specific NativeRegisterContextLinux. The - // implementations can't collide - // as only one NativeRegisterContextLinux_* variant should be compiled into - // the final - // executable. - static NativeRegisterContextLinux * + // to create a new instance of the host specific NativeRegisterContextLinux. + // The implementations can't collide as only one NativeRegisterContextLinux_* + // variant should be compiled into the final executable. + static std::unique_ptr<NativeRegisterContextLinux> CreateHostNativeRegisterContextLinux(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeThreadProtocol &native_thread); protected: lldb::ByteOrder GetByteOrder() const; diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp index 22b7d10869fe0..cb05416cb6c33 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp @@ -11,15 +11,15 @@ #include "NativeRegisterContextLinux_arm.h" +#include "Plugins/Process/Linux/NativeProcessLinux.h" +#include "Plugins/Process/Linux/Procfs.h" +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" +#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" -#include "Plugins/Process/Linux/Procfs.h" -#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" -#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h" - #include <elf.h> #include <sys/socket.h> @@ -95,20 +95,18 @@ static const RegisterSet g_reg_sets_arm[k_num_register_sets] = { #if defined(__arm__) -NativeRegisterContextLinux * +std::unique_ptr<NativeRegisterContextLinux> NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) { - return new NativeRegisterContextLinux_arm(target_arch, native_thread, - concrete_frame_idx); + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { + return llvm::make_unique<NativeRegisterContextLinux_arm>(target_arch, + native_thread); } #endif // defined(__arm__) NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) - : NativeRegisterContextLinux(native_thread, concrete_frame_idx, + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) + : NativeRegisterContextLinux(native_thread, new RegisterInfoPOSIX_arm(target_arch)) { switch (target_arch.GetMachine()) { case llvm::Triple::arm: diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h index ec99c05e16444..40e3b80eda743 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h @@ -23,8 +23,7 @@ class NativeProcessLinux; class NativeRegisterContextLinux_arm : public NativeRegisterContextLinux { public: NativeRegisterContextLinux_arm(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeThreadProtocol &native_thread); uint32_t GetRegisterSetCount() const override; diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp index 7aad062e3f93d..c483260a5b2c8 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -112,26 +112,24 @@ static const RegisterSet g_reg_sets_arm64[k_num_register_sets] = { {"Floating Point Registers", "fpu", k_num_fpr_registers_arm64, g_fpu_regnums_arm64}}; -NativeRegisterContextLinux * +std::unique_ptr<NativeRegisterContextLinux> NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) { + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { switch (target_arch.GetMachine()) { case llvm::Triple::arm: - return new NativeRegisterContextLinux_arm(target_arch, native_thread, - concrete_frame_idx); + return llvm::make_unique<NativeRegisterContextLinux_arm>(target_arch, + native_thread); case llvm::Triple::aarch64: - return new NativeRegisterContextLinux_arm64(target_arch, native_thread, - concrete_frame_idx); + return llvm::make_unique<NativeRegisterContextLinux_arm64>(target_arch, + native_thread); default: llvm_unreachable("have no register context for architecture"); } } NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) - : NativeRegisterContextLinux(native_thread, concrete_frame_idx, + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) + : NativeRegisterContextLinux(native_thread, new RegisterInfoPOSIX_arm64(target_arch)) { switch (target_arch.GetMachine()) { case llvm::Triple::aarch64: @@ -872,12 +870,8 @@ Status NativeRegisterContextLinux_arm64::DoReadRegisterValue( error = NativeProcessLinux::PtraceWrapper( PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, sizeof regs); if (error.Success()) { - ArchSpec arch; - if (m_thread.GetProcess().GetArchitecture(arch)) - value.SetBytes((void *)(((unsigned char *)(®s)) + offset), 16, - arch.GetByteOrder()); - else - error.SetErrorString("failed to get architecture"); + value.SetBytes((void *)(((unsigned char *)(®s)) + offset), 16, + m_thread.GetProcess().GetByteOrder()); } } else { elf_gregset_t regs; @@ -889,12 +883,8 @@ Status NativeRegisterContextLinux_arm64::DoReadRegisterValue( error = NativeProcessLinux::PtraceWrapper( PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, sizeof regs); if (error.Success()) { - ArchSpec arch; - if (m_thread.GetProcess().GetArchitecture(arch)) - value.SetBytes((void *)(((unsigned char *)(regs)) + offset), 8, - arch.GetByteOrder()); - else - error.SetErrorString("failed to get architecture"); + value.SetBytes((void *)(((unsigned char *)(regs)) + offset), 8, + m_thread.GetProcess().GetByteOrder()); } } return error; diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h index 9877dec37c48e..ab3c881ead598 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h @@ -23,8 +23,7 @@ class NativeProcessLinux; class NativeRegisterContextLinux_arm64 : public NativeRegisterContextLinux { public: NativeRegisterContextLinux_arm64(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeThreadProtocol &native_thread); uint32_t GetRegisterSetCount() const override; diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp index f35ff2be0d94d..32c04a4374e62 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp @@ -80,12 +80,11 @@ struct pt_watch_regs default_watch_regs; using namespace lldb_private; using namespace lldb_private::process_linux; -NativeRegisterContextLinux * +std::unique_ptr<NativeRegisterContextLinux> NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) { - return new NativeRegisterContextLinux_mips64(target_arch, native_thread, - concrete_frame_idx); + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { + return llvm::make_unique<NativeRegisterContextLinux_mips64>(target_arch, + native_thread); } #define REG_CONTEXT_SIZE \ @@ -110,9 +109,8 @@ CreateRegisterInfoInterface(const ArchSpec &target_arch) { } NativeRegisterContextLinux_mips64::NativeRegisterContextLinux_mips64( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) - : NativeRegisterContextLinux(native_thread, concrete_frame_idx, + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) + : NativeRegisterContextLinux(native_thread, CreateRegisterInfoInterface(target_arch)) { switch (target_arch.GetMachine()) { case llvm::Triple::mips: @@ -1033,13 +1031,11 @@ Status NativeRegisterContextLinux_mips64::Read_SR_Config(uint32_t offset, Status error = NativeProcessLinux::PtraceWrapper( PTRACE_GETREGS, m_thread.GetID(), NULL, ®s, sizeof regs); if (error.Success()) { - lldb_private::ArchSpec arch; - if (m_thread.GetProcess().GetArchitecture(arch)) { - void *target_address = ((uint8_t *)®s) + offset + - 4 * (arch.GetMachine() == llvm::Triple::mips); - value.SetUInt(*(uint32_t *)target_address, size); - } else - error.SetErrorString("failed to get architecture"); + const lldb_private::ArchSpec &arch = + m_thread.GetProcess().GetArchitecture(); + void *target_address = ((uint8_t *)®s) + offset + + 4 * (arch.GetMachine() == llvm::Triple::mips); + value.SetUInt(*(uint32_t *)target_address, size); } return error; } diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h index 3e14da5a27257..c4e984a545bc6 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h @@ -15,6 +15,7 @@ #include "Plugins/Process/Linux/NativeRegisterContextLinux.h" #include "Plugins/Process/Utility/RegisterContext_mips.h" #include "Plugins/Process/Utility/lldb-mips-linux-register-enums.h" +#include <sys/uio.h> #define MAX_NUM_WP 8 @@ -26,8 +27,7 @@ class NativeProcessLinux; class NativeRegisterContextLinux_mips64 : public NativeRegisterContextLinux { public: NativeRegisterContextLinux_mips64(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeThreadProtocol &native_thread); uint32_t GetRegisterSetCount() const override; @@ -129,7 +129,7 @@ private: lldb::addr_t hw_addr_map[MAX_NUM_WP]; - IOVEC_mips m_iovec; + struct iovec m_iovec; }; } // namespace process_linux diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp new file mode 100644 index 0000000000000..ea854dfa1dc6d --- /dev/null +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp @@ -0,0 +1,801 @@ +//===-- NativeRegisterContextLinux_ppc64le.cpp ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// This implementation is related to the OpenPOWER ABI for Power Architecture +// 64-bit ELF V2 ABI + +#if defined(__powerpc64__) + +#include "NativeRegisterContextLinux_ppc64le.h" + +#include "lldb/Core/RegisterValue.h" +#include "lldb/Host/common/NativeProcessProtocol.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Status.h" + +#include "Plugins/Process/Linux/NativeProcessLinux.h" +#include "Plugins/Process/Linux/Procfs.h" +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" +#include "Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h" + +// System includes - They have to be included after framework includes because +// they define some +// macros which collide with variable names in other modules +#include <sys/socket.h> +#include <elf.h> +#include <asm/ptrace.h> + +#define REG_CONTEXT_SIZE \ + (GetGPRSize() + GetFPRSize() + sizeof(m_vmx_ppc64le) + sizeof(m_vsx_ppc64le)) +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::process_linux; + +static const uint32_t g_gpr_regnums_ppc64le[] = { + gpr_r0_ppc64le, gpr_r1_ppc64le, gpr_r2_ppc64le, gpr_r3_ppc64le, + gpr_r4_ppc64le, gpr_r5_ppc64le, gpr_r6_ppc64le, gpr_r7_ppc64le, + gpr_r8_ppc64le, gpr_r9_ppc64le, gpr_r10_ppc64le, gpr_r11_ppc64le, + gpr_r12_ppc64le, gpr_r13_ppc64le, gpr_r14_ppc64le, gpr_r15_ppc64le, + gpr_r16_ppc64le, gpr_r17_ppc64le, gpr_r18_ppc64le, gpr_r19_ppc64le, + gpr_r20_ppc64le, gpr_r21_ppc64le, gpr_r22_ppc64le, gpr_r23_ppc64le, + gpr_r24_ppc64le, gpr_r25_ppc64le, gpr_r26_ppc64le, gpr_r27_ppc64le, + gpr_r28_ppc64le, gpr_r29_ppc64le, gpr_r30_ppc64le, gpr_r31_ppc64le, + gpr_pc_ppc64le, gpr_msr_ppc64le, gpr_origr3_ppc64le, gpr_ctr_ppc64le, + gpr_lr_ppc64le, gpr_xer_ppc64le, gpr_cr_ppc64le, gpr_softe_ppc64le, + gpr_trap_ppc64le, +}; + +static const uint32_t g_fpr_regnums_ppc64le[] = { + fpr_f0_ppc64le, fpr_f1_ppc64le, fpr_f2_ppc64le, fpr_f3_ppc64le, + fpr_f4_ppc64le, fpr_f5_ppc64le, fpr_f6_ppc64le, fpr_f7_ppc64le, + fpr_f8_ppc64le, fpr_f9_ppc64le, fpr_f10_ppc64le, fpr_f11_ppc64le, + fpr_f12_ppc64le, fpr_f13_ppc64le, fpr_f14_ppc64le, fpr_f15_ppc64le, + fpr_f16_ppc64le, fpr_f17_ppc64le, fpr_f18_ppc64le, fpr_f19_ppc64le, + fpr_f20_ppc64le, fpr_f21_ppc64le, fpr_f22_ppc64le, fpr_f23_ppc64le, + fpr_f24_ppc64le, fpr_f25_ppc64le, fpr_f26_ppc64le, fpr_f27_ppc64le, + fpr_f28_ppc64le, fpr_f29_ppc64le, fpr_f30_ppc64le, fpr_f31_ppc64le, + fpr_fpscr_ppc64le, +}; + +static const uint32_t g_vmx_regnums_ppc64le[] = { + vmx_vr0_ppc64le, vmx_vr1_ppc64le, vmx_vr2_ppc64le, vmx_vr3_ppc64le, + vmx_vr4_ppc64le, vmx_vr5_ppc64le, vmx_vr6_ppc64le, vmx_vr7_ppc64le, + vmx_vr8_ppc64le, vmx_vr9_ppc64le, vmx_vr10_ppc64le, vmx_vr11_ppc64le, + vmx_vr12_ppc64le, vmx_vr13_ppc64le, vmx_vr14_ppc64le, vmx_vr15_ppc64le, + vmx_vr16_ppc64le, vmx_vr17_ppc64le, vmx_vr18_ppc64le, vmx_vr19_ppc64le, + vmx_vr20_ppc64le, vmx_vr21_ppc64le, vmx_vr22_ppc64le, vmx_vr23_ppc64le, + vmx_vr24_ppc64le, vmx_vr25_ppc64le, vmx_vr26_ppc64le, vmx_vr27_ppc64le, + vmx_vr28_ppc64le, vmx_vr29_ppc64le, vmx_vr30_ppc64le, vmx_vr31_ppc64le, + vmx_vscr_ppc64le, vmx_vrsave_ppc64le, +}; + +static const uint32_t g_vsx_regnums_ppc64le[] = { + vsx_vs0_ppc64le, vsx_vs1_ppc64le, vsx_vs2_ppc64le, vsx_vs3_ppc64le, + vsx_vs4_ppc64le, vsx_vs5_ppc64le, vsx_vs6_ppc64le, vsx_vs7_ppc64le, + vsx_vs8_ppc64le, vsx_vs9_ppc64le, vsx_vs10_ppc64le, vsx_vs11_ppc64le, + vsx_vs12_ppc64le, vsx_vs13_ppc64le, vsx_vs14_ppc64le, vsx_vs15_ppc64le, + vsx_vs16_ppc64le, vsx_vs17_ppc64le, vsx_vs18_ppc64le, vsx_vs19_ppc64le, + vsx_vs20_ppc64le, vsx_vs21_ppc64le, vsx_vs22_ppc64le, vsx_vs23_ppc64le, + vsx_vs24_ppc64le, vsx_vs25_ppc64le, vsx_vs26_ppc64le, vsx_vs27_ppc64le, + vsx_vs28_ppc64le, vsx_vs29_ppc64le, vsx_vs30_ppc64le, vsx_vs31_ppc64le, + vsx_vs32_ppc64le, vsx_vs33_ppc64le, vsx_vs34_ppc64le, vsx_vs35_ppc64le, + vsx_vs36_ppc64le, vsx_vs37_ppc64le, vsx_vs38_ppc64le, vsx_vs39_ppc64le, + vsx_vs40_ppc64le, vsx_vs41_ppc64le, vsx_vs42_ppc64le, vsx_vs43_ppc64le, + vsx_vs44_ppc64le, vsx_vs45_ppc64le, vsx_vs46_ppc64le, vsx_vs47_ppc64le, + vsx_vs48_ppc64le, vsx_vs49_ppc64le, vsx_vs50_ppc64le, vsx_vs51_ppc64le, + vsx_vs52_ppc64le, vsx_vs53_ppc64le, vsx_vs54_ppc64le, vsx_vs55_ppc64le, + vsx_vs56_ppc64le, vsx_vs57_ppc64le, vsx_vs58_ppc64le, vsx_vs59_ppc64le, + vsx_vs60_ppc64le, vsx_vs61_ppc64le, vsx_vs62_ppc64le, vsx_vs63_ppc64le, +}; + +namespace { +// Number of register sets provided by this context. +enum { k_num_register_sets = 4 }; +} + +static const RegisterSet g_reg_sets_ppc64le[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_ppc64le, + g_gpr_regnums_ppc64le}, + {"Floating Point Registers", "fpr", k_num_fpr_registers_ppc64le, + g_fpr_regnums_ppc64le}, + {"AltiVec/VMX Registers", "vmx", k_num_vmx_registers_ppc64le, + g_vmx_regnums_ppc64le}, + {"VSX Registers", "vsx", k_num_vsx_registers_ppc64le, + g_vsx_regnums_ppc64le}, +}; + +std::unique_ptr<NativeRegisterContextLinux> +NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { + switch (target_arch.GetMachine()) { + case llvm::Triple::ppc64le: + return llvm::make_unique<NativeRegisterContextLinux_ppc64le>(target_arch, + native_thread); + default: + llvm_unreachable("have no register context for architecture"); + } +} + +NativeRegisterContextLinux_ppc64le::NativeRegisterContextLinux_ppc64le( + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) + : NativeRegisterContextLinux(native_thread, + new RegisterInfoPOSIX_ppc64le(target_arch)) { + if (target_arch.GetMachine() != llvm::Triple::ppc64le) { + llvm_unreachable("Unhandled target architecture."); + } + + ::memset(&m_gpr_ppc64le, 0, sizeof(m_gpr_ppc64le)); + ::memset(&m_fpr_ppc64le, 0, sizeof(m_fpr_ppc64le)); + ::memset(&m_vmx_ppc64le, 0, sizeof(m_vmx_ppc64le)); + ::memset(&m_vsx_ppc64le, 0, sizeof(m_vsx_ppc64le)); + ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs)); +} + +uint32_t NativeRegisterContextLinux_ppc64le::GetRegisterSetCount() const { + return k_num_register_sets; +} + +const RegisterSet * +NativeRegisterContextLinux_ppc64le::GetRegisterSet(uint32_t set_index) const { + if (set_index < k_num_register_sets) + return &g_reg_sets_ppc64le[set_index]; + + return nullptr; +} + +uint32_t NativeRegisterContextLinux_ppc64le::GetUserRegisterCount() const { + uint32_t count = 0; + for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) + count += g_reg_sets_ppc64le[set_index].num_registers; + return count; +} + +Status NativeRegisterContextLinux_ppc64le::ReadRegister( + const RegisterInfo *reg_info, RegisterValue ®_value) { + Status error; + + if (!reg_info) { + error.SetErrorString("reg_info NULL"); + return error; + } + + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + + if (IsFPR(reg)) { + error = ReadFPR(); + if (error.Fail()) + return error; + + // Get pointer to m_fpr_ppc64le variable and set the data from it. + uint32_t fpr_offset = CalculateFprOffset(reg_info); + assert(fpr_offset < sizeof m_fpr_ppc64le); + uint8_t *src = (uint8_t *)&m_fpr_ppc64le + fpr_offset; + reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, + eByteOrderLittle, error); + } else if (IsVSX(reg)) { + uint32_t vsx_offset = CalculateVsxOffset(reg_info); + assert(vsx_offset < sizeof(m_vsx_ppc64le)); + + if (vsx_offset < sizeof(m_vsx_ppc64le) / 2) { + error = ReadVSX(); + if (error.Fail()) + return error; + + error = ReadFPR(); + if (error.Fail()) + return error; + + uint64_t value[2]; + uint8_t *dst, *src; + dst = (uint8_t *)&value; + src = (uint8_t *)&m_vsx_ppc64le + vsx_offset / 2; + ::memcpy(dst, src, 8); + dst += 8; + src = (uint8_t *)&m_fpr_ppc64le + vsx_offset / 2; + ::memcpy(dst, src, 8); + reg_value.SetFromMemoryData(reg_info, &value, reg_info->byte_size, + eByteOrderLittle, error); + } else { + error = ReadVMX(); + if (error.Fail()) + return error; + + // Get pointer to m_vmx_ppc64le variable and set the data from it. + uint32_t vmx_offset = vsx_offset - sizeof(m_vsx_ppc64le) / 2; + uint8_t *src = (uint8_t *)&m_vmx_ppc64le + vmx_offset; + reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, + eByteOrderLittle, error); + } + } else if (IsVMX(reg)) { + error = ReadVMX(); + if (error.Fail()) + return error; + + // Get pointer to m_vmx_ppc64le variable and set the data from it. + uint32_t vmx_offset = CalculateVmxOffset(reg_info); + assert(vmx_offset < sizeof m_vmx_ppc64le); + uint8_t *src = (uint8_t *)&m_vmx_ppc64le + vmx_offset; + reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, + eByteOrderLittle, error); + } else if (IsGPR(reg)) { + error = ReadGPR(); + if (error.Fail()) + return error; + + uint8_t *src = (uint8_t *) &m_gpr_ppc64le + reg_info->byte_offset; + reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, + eByteOrderLittle, error); + } else { + return Status("failed - register wasn't recognized to be a GPR, FPR, VSX " + "or VMX, read strategy unknown"); + } + + return error; +} + +Status NativeRegisterContextLinux_ppc64le::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue ®_value) { + Status error; + if (!reg_info) + return Status("reg_info NULL"); + + const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg_index == LLDB_INVALID_REGNUM) + return Status("no lldb regnum for %s", reg_info && reg_info->name + ? reg_info->name + : "<unknown register>"); + + if (IsGPR(reg_index)) { + error = ReadGPR(); + if (error.Fail()) + return error; + + uint8_t *dst = (uint8_t *)&m_gpr_ppc64le + reg_info->byte_offset; + ::memcpy(dst, reg_value.GetBytes(), reg_value.GetByteSize()); + + error = WriteGPR(); + if (error.Fail()) + return error; + + return Status(); + } + + if (IsFPR(reg_index)) { + error = ReadFPR(); + if (error.Fail()) + return error; + + // Get pointer to m_fpr_ppc64le variable and set the data to it. + uint32_t fpr_offset = CalculateFprOffset(reg_info); + assert(fpr_offset < GetFPRSize()); + uint8_t *dst = (uint8_t *)&m_fpr_ppc64le + fpr_offset; + ::memcpy(dst, reg_value.GetBytes(), reg_value.GetByteSize()); + + error = WriteFPR(); + if (error.Fail()) + return error; + + return Status(); + } + + if (IsVMX(reg_index)) { + error = ReadVMX(); + if (error.Fail()) + return error; + + // Get pointer to m_vmx_ppc64le variable and set the data to it. + uint32_t vmx_offset = CalculateVmxOffset(reg_info); + assert(vmx_offset < sizeof(m_vmx_ppc64le)); + uint8_t *dst = (uint8_t *)&m_vmx_ppc64le + vmx_offset; + ::memcpy(dst, reg_value.GetBytes(), reg_value.GetByteSize()); + + error = WriteVMX(); + if (error.Fail()) + return error; + + return Status(); + } + + if (IsVSX(reg_index)) { + uint32_t vsx_offset = CalculateVsxOffset(reg_info); + assert(vsx_offset < sizeof(m_vsx_ppc64le)); + + if (vsx_offset < sizeof(m_vsx_ppc64le) / 2) { + error = ReadVSX(); + if (error.Fail()) + return error; + + error = ReadFPR(); + if (error.Fail()) + return error; + + uint64_t value[2]; + ::memcpy(value, reg_value.GetBytes(), 16); + uint8_t *dst, *src; + src = (uint8_t *)value; + dst = (uint8_t *)&m_vsx_ppc64le + vsx_offset / 2; + ::memcpy(dst, src, 8); + src += 8; + dst = (uint8_t *)&m_fpr_ppc64le + vsx_offset / 2; + ::memcpy(dst, src, 8); + + WriteVSX(); + WriteFPR(); + } else { + error = ReadVMX(); + if (error.Fail()) + return error; + + // Get pointer to m_vmx_ppc64le variable and set the data from it. + uint32_t vmx_offset = vsx_offset - sizeof(m_vsx_ppc64le) / 2; + uint8_t *dst = (uint8_t *)&m_vmx_ppc64le + vmx_offset; + ::memcpy(dst, reg_value.GetBytes(), reg_value.GetByteSize()); + WriteVMX(); + } + + return Status(); + } + + return Status("failed - register wasn't recognized to be a GPR, FPR, VSX " + "or VMX, write strategy unknown"); +} + +Status NativeRegisterContextLinux_ppc64le::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + Status error; + + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + if (!data_sp) + return Status("failed to allocate DataBufferHeap instance of size %" PRIu64, + REG_CONTEXT_SIZE); + + error = ReadGPR(); + if (error.Fail()) + return error; + + error = ReadFPR(); + if (error.Fail()) + return error; + + error = ReadVMX(); + if (error.Fail()) + return error; + + error = ReadVSX(); + if (error.Fail()) + return error; + + uint8_t *dst = data_sp->GetBytes(); + if (dst == nullptr) { + error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 + " returned a null pointer", + REG_CONTEXT_SIZE); + return error; + } + + ::memcpy(dst, &m_gpr_ppc64le, GetGPRSize()); + dst += GetGPRSize(); + ::memcpy(dst, &m_fpr_ppc64le, GetFPRSize()); + dst += GetFPRSize(); + ::memcpy(dst, &m_vmx_ppc64le, sizeof(m_vmx_ppc64le)); + dst += sizeof(m_vmx_ppc64le); + ::memcpy(dst, &m_vsx_ppc64le, sizeof(m_vsx_ppc64le)); + + return error; +} + +Status NativeRegisterContextLinux_ppc64le::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + Status error; + + if (!data_sp) { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_ppc64le::%s invalid data_sp provided", + __FUNCTION__); + return error; + } + + if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_ppc64le::%s data_sp contained mismatched " + "data size, expected %" PRIu64 ", actual %" PRIu64, + __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); + return error; + } + + uint8_t *src = data_sp->GetBytes(); + if (src == nullptr) { + error.SetErrorStringWithFormat("NativeRegisterContextLinux_ppc64le::%s " + "DataBuffer::GetBytes() returned a null " + "pointer", + __FUNCTION__); + return error; + } + + ::memcpy(&m_gpr_ppc64le, src, GetGPRSize()); + error = WriteGPR(); + + if (error.Fail()) + return error; + + src += GetGPRSize(); + ::memcpy(&m_fpr_ppc64le, src, GetFPRSize()); + + error = WriteFPR(); + if (error.Fail()) + return error; + + src += GetFPRSize(); + ::memcpy(&m_vmx_ppc64le, src, sizeof(m_vmx_ppc64le)); + + error = WriteVMX(); + if (error.Fail()) + return error; + + src += sizeof(m_vmx_ppc64le); + ::memcpy(&m_vsx_ppc64le, src, sizeof(m_vsx_ppc64le)); + error = WriteVSX(); + + return error; +} + +bool NativeRegisterContextLinux_ppc64le::IsGPR(unsigned reg) const { + return reg <= k_last_gpr_ppc64le; // GPR's come first. +} + +bool NativeRegisterContextLinux_ppc64le::IsFPR(unsigned reg) const { + return (k_first_fpr_ppc64le <= reg && reg <= k_last_fpr_ppc64le); +} + +Status NativeRegisterContextLinux_ppc64le::DoReadGPR( + void *buf, size_t buf_size) { + int regset = NT_PRSTATUS; + return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_thread.GetID(), + ®set, buf, buf_size); +} + +Status NativeRegisterContextLinux_ppc64le::DoWriteGPR( + void *buf, size_t buf_size) { + int regset = NT_PRSTATUS; + return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGS, m_thread.GetID(), + ®set, buf, buf_size); +} + +Status NativeRegisterContextLinux_ppc64le::DoReadFPR(void *buf, + size_t buf_size) { + int regset = NT_FPREGSET; + return NativeProcessLinux::PtraceWrapper(PTRACE_GETFPREGS, m_thread.GetID(), + ®set, buf, buf_size); +} + +Status NativeRegisterContextLinux_ppc64le::DoWriteFPR(void *buf, + size_t buf_size) { + int regset = NT_FPREGSET; + return NativeProcessLinux::PtraceWrapper(PTRACE_SETFPREGS, m_thread.GetID(), + ®set, buf, buf_size); +} + +uint32_t NativeRegisterContextLinux_ppc64le::CalculateFprOffset( + const RegisterInfo *reg_info) const { + return reg_info->byte_offset - + GetRegisterInfoAtIndex(k_first_fpr_ppc64le)->byte_offset; +} + +uint32_t NativeRegisterContextLinux_ppc64le::CalculateVmxOffset( + const RegisterInfo *reg_info) const { + return reg_info->byte_offset - + GetRegisterInfoAtIndex(k_first_vmx_ppc64le)->byte_offset; +} + +uint32_t NativeRegisterContextLinux_ppc64le::CalculateVsxOffset( + const RegisterInfo *reg_info) const { + return reg_info->byte_offset - + GetRegisterInfoAtIndex(k_first_vsx_ppc64le)->byte_offset; +} + +Status NativeRegisterContextLinux_ppc64le::ReadVMX() { + int regset = NT_PPC_VMX; + return NativeProcessLinux::PtraceWrapper(PTRACE_GETVRREGS, m_thread.GetID(), + ®set, &m_vmx_ppc64le, + sizeof(m_vmx_ppc64le)); +} + +Status NativeRegisterContextLinux_ppc64le::WriteVMX() { + int regset = NT_PPC_VMX; + return NativeProcessLinux::PtraceWrapper(PTRACE_SETVRREGS, m_thread.GetID(), + ®set, &m_vmx_ppc64le, + sizeof(m_vmx_ppc64le)); +} + +Status NativeRegisterContextLinux_ppc64le::ReadVSX() { + int regset = NT_PPC_VSX; + return NativeProcessLinux::PtraceWrapper(PTRACE_GETVSRREGS, m_thread.GetID(), + ®set, &m_vsx_ppc64le, + sizeof(m_vsx_ppc64le)); +} + +Status NativeRegisterContextLinux_ppc64le::WriteVSX() { + int regset = NT_PPC_VSX; + return NativeProcessLinux::PtraceWrapper(PTRACE_SETVSRREGS, m_thread.GetID(), + ®set, &m_vsx_ppc64le, + sizeof(m_vsx_ppc64le)); +} + +bool NativeRegisterContextLinux_ppc64le::IsVMX(unsigned reg) { + return (reg >= k_first_vmx_ppc64le) && (reg <= k_last_vmx_ppc64le); +} + +bool NativeRegisterContextLinux_ppc64le::IsVSX(unsigned reg) { + return (reg >= k_first_vsx_ppc64le) && (reg <= k_last_vsx_ppc64le); +} + +uint32_t NativeRegisterContextLinux_ppc64le::NumSupportedHardwareWatchpoints() { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + + // Read hardware breakpoint and watchpoint information. + Status error = ReadHardwareDebugInfo(); + + if (error.Fail()) + return 0; + + LLDB_LOG(log, "{0}", m_max_hwp_supported); + return m_max_hwp_supported; +} + +uint32_t NativeRegisterContextLinux_ppc64le::SetHardwareWatchpoint( + lldb::addr_t addr, size_t size, uint32_t watch_flags) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size, + watch_flags); + + // Read hardware breakpoint and watchpoint information. + Status error = ReadHardwareDebugInfo(); + + if (error.Fail()) + return LLDB_INVALID_INDEX32; + + uint32_t control_value = 0, wp_index = 0; + lldb::addr_t real_addr = addr; + uint32_t rw_mode = 0; + + // Check if we are setting watchpoint other than read/write/access + // Update watchpoint flag to match ppc64le write-read bit configuration. + switch (watch_flags) { + case eWatchpointKindWrite: + rw_mode = PPC_BREAKPOINT_TRIGGER_WRITE; + watch_flags = 2; + break; + case eWatchpointKindRead: + rw_mode = PPC_BREAKPOINT_TRIGGER_READ; + watch_flags = 1; + break; + case (eWatchpointKindRead | eWatchpointKindWrite): + rw_mode = PPC_BREAKPOINT_TRIGGER_RW; + break; + default: + return LLDB_INVALID_INDEX32; + } + + // Check if size has a valid hardware watchpoint length. + if (size != 1 && size != 2 && size != 4 && size != 8) + return LLDB_INVALID_INDEX32; + + // Check 8-byte alignment for hardware watchpoint target address. + // Below is a hack to recalculate address and size in order to + // make sure we can watch non 8-byte alligned addresses as well. + if (addr & 0x07) { + + addr_t begin = llvm::alignDown(addr, 8); + addr_t end = llvm::alignTo(addr + size, 8); + size = llvm::PowerOf2Ceil(end - begin); + + addr = addr & (~0x07); + } + + // Setup control value + control_value = watch_flags << 3; + control_value |= ((1 << size) - 1) << 5; + control_value |= (2 << 1) | 1; + + // Iterate over stored watchpoints and find a free wp_index + wp_index = LLDB_INVALID_INDEX32; + for (uint32_t i = 0; i < m_max_hwp_supported; i++) { + if ((m_hwp_regs[i].control & 1) == 0) { + wp_index = i; // Mark last free slot + } else if (m_hwp_regs[i].address == addr) { + return LLDB_INVALID_INDEX32; // We do not support duplicate watchpoints. + } + } + + if (wp_index == LLDB_INVALID_INDEX32) + return LLDB_INVALID_INDEX32; + + // Update watchpoint in local cache + m_hwp_regs[wp_index].real_addr = real_addr; + m_hwp_regs[wp_index].address = addr; + m_hwp_regs[wp_index].control = control_value; + m_hwp_regs[wp_index].mode = rw_mode; + + // PTRACE call to set corresponding watchpoint register. + error = WriteHardwareDebugRegs(); + + if (error.Fail()) { + m_hwp_regs[wp_index].address = 0; + m_hwp_regs[wp_index].control &= llvm::maskTrailingZeros<uint32_t>(1); + + return LLDB_INVALID_INDEX32; + } + + return wp_index; +} + +bool NativeRegisterContextLinux_ppc64le::ClearHardwareWatchpoint( + uint32_t wp_index) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "wp_index: {0}", wp_index); + + // Read hardware breakpoint and watchpoint information. + Status error = ReadHardwareDebugInfo(); + + if (error.Fail()) + return false; + + if (wp_index >= m_max_hwp_supported) + return false; + + // Create a backup we can revert to in case of failure. + lldb::addr_t tempAddr = m_hwp_regs[wp_index].address; + uint32_t tempControl = m_hwp_regs[wp_index].control; + long *tempSlot = reinterpret_cast<long *>(m_hwp_regs[wp_index].slot); + + // Update watchpoint in local cache + m_hwp_regs[wp_index].control &= llvm::maskTrailingZeros<uint32_t>(1); + m_hwp_regs[wp_index].address = 0; + m_hwp_regs[wp_index].slot = 0; + m_hwp_regs[wp_index].mode = 0; + + // Ptrace call to update hardware debug registers + error = NativeProcessLinux::PtraceWrapper(PPC_PTRACE_DELHWDEBUG, + m_thread.GetID(), 0, tempSlot); + + if (error.Fail()) { + m_hwp_regs[wp_index].control = tempControl; + m_hwp_regs[wp_index].address = tempAddr; + m_hwp_regs[wp_index].slot = reinterpret_cast<long>(tempSlot); + + return false; + } + + return true; +} + +uint32_t +NativeRegisterContextLinux_ppc64le::GetWatchpointSize(uint32_t wp_index) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "wp_index: {0}", wp_index); + + unsigned control = (m_hwp_regs[wp_index].control >> 5) & 0xff; + if (llvm::isPowerOf2_32(control + 1)) { + return llvm::countPopulation(control); + } + + return 0; +} + +bool NativeRegisterContextLinux_ppc64le::WatchpointIsEnabled( + uint32_t wp_index) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "wp_index: {0}", wp_index); + + return !!((m_hwp_regs[wp_index].control & 0x1) == 0x1); +} + +Status NativeRegisterContextLinux_ppc64le::GetWatchpointHitIndex( + uint32_t &wp_index, lldb::addr_t trap_addr) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr); + + uint32_t watch_size; + lldb::addr_t watch_addr; + + for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) { + watch_size = GetWatchpointSize(wp_index); + watch_addr = m_hwp_regs[wp_index].address; + + if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr && + trap_addr <= watch_addr + watch_size) { + m_hwp_regs[wp_index].hit_addr = trap_addr; + return Status(); + } + } + + wp_index = LLDB_INVALID_INDEX32; + return Status(); +} + +lldb::addr_t +NativeRegisterContextLinux_ppc64le::GetWatchpointAddress(uint32_t wp_index) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "wp_index: {0}", wp_index); + + if (wp_index >= m_max_hwp_supported) + return LLDB_INVALID_ADDRESS; + + if (WatchpointIsEnabled(wp_index)) + return m_hwp_regs[wp_index].real_addr; + else + return LLDB_INVALID_ADDRESS; +} + +lldb::addr_t +NativeRegisterContextLinux_ppc64le::GetWatchpointHitAddress(uint32_t wp_index) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "wp_index: {0}", wp_index); + + if (wp_index >= m_max_hwp_supported) + return LLDB_INVALID_ADDRESS; + + if (WatchpointIsEnabled(wp_index)) + return m_hwp_regs[wp_index].hit_addr; + + return LLDB_INVALID_ADDRESS; +} + +Status NativeRegisterContextLinux_ppc64le::ReadHardwareDebugInfo() { + if (!m_refresh_hwdebug_info) { + return Status(); + } + + ::pid_t tid = m_thread.GetID(); + + struct ppc_debug_info hwdebug_info; + Status error; + + error = NativeProcessLinux::PtraceWrapper( + PPC_PTRACE_GETHWDBGINFO, tid, 0, &hwdebug_info, sizeof(hwdebug_info)); + + if (error.Fail()) + return error; + + m_max_hwp_supported = hwdebug_info.num_data_bps; + m_max_hbp_supported = hwdebug_info.num_instruction_bps; + m_refresh_hwdebug_info = false; + + return error; +} + +Status NativeRegisterContextLinux_ppc64le::WriteHardwareDebugRegs() { + struct ppc_hw_breakpoint reg_state; + Status error; + long ret; + + for (uint32_t i = 0; i < m_max_hwp_supported; i++) { + reg_state.addr = m_hwp_regs[i].address; + reg_state.trigger_type = m_hwp_regs[i].mode; + reg_state.version = 1; + reg_state.addr_mode = PPC_BREAKPOINT_MODE_EXACT; + reg_state.condition_mode = PPC_BREAKPOINT_CONDITION_NONE; + reg_state.addr2 = 0; + reg_state.condition_value = 0; + + error = NativeProcessLinux::PtraceWrapper(PPC_PTRACE_SETHWDEBUG, + m_thread.GetID(), 0, ®_state, + sizeof(reg_state), &ret); + + if (error.Fail()) + return error; + + m_hwp_regs[i].slot = ret; + } + + return error; +} + +#endif // defined(__powerpc64__) diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.h new file mode 100644 index 0000000000000..bb25af80d02cd --- /dev/null +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.h @@ -0,0 +1,149 @@ +//===-- NativeRegisterContextLinux_ppc64le.h --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// This implementation is related to the OpenPOWER ABI for Power Architecture +// 64-bit ELF V2 ABI + +#if defined(__powerpc64__) + +#ifndef lldb_NativeRegisterContextLinux_ppc64le_h +#define lldb_NativeRegisterContextLinux_ppc64le_h + +#include "Plugins/Process/Linux/NativeRegisterContextLinux.h" +#include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h" + +#define DECLARE_REGISTER_INFOS_PPC64LE_STRUCT +#include "RegisterInfos_ppc64le.h" +#undef DECLARE_REGISTER_INFOS_PPC64LE_STRUCT + +namespace lldb_private { +namespace process_linux { + +class NativeProcessLinux; + +class NativeRegisterContextLinux_ppc64le : public NativeRegisterContextLinux { +public: + NativeRegisterContextLinux_ppc64le(const ArchSpec &target_arch, + NativeThreadProtocol &native_thread); + + uint32_t GetRegisterSetCount() const override; + + uint32_t GetUserRegisterCount() const override; + + const RegisterSet *GetRegisterSet(uint32_t set_index) const override; + + Status ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) override; + + Status WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; + + Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + + Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + + //------------------------------------------------------------------ + // Hardware watchpoint mangement functions + //------------------------------------------------------------------ + + uint32_t NumSupportedHardwareWatchpoints() override; + + uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, + uint32_t watch_flags) override; + + bool ClearHardwareWatchpoint(uint32_t hw_index) override; + + Status GetWatchpointHitIndex(uint32_t &wp_index, + lldb::addr_t trap_addr) override; + + lldb::addr_t GetWatchpointHitAddress(uint32_t wp_index) override; + + lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override; + + uint32_t GetWatchpointSize(uint32_t wp_index); + + bool WatchpointIsEnabled(uint32_t wp_index); + +protected: + Status DoReadGPR(void *buf, size_t buf_size) override; + + Status DoWriteGPR(void *buf, size_t buf_size) override; + + Status DoReadFPR(void *buf, size_t buf_size) override; + + Status DoWriteFPR(void *buf, size_t buf_size) override; + + bool IsVMX(unsigned reg); + + bool IsVSX(unsigned reg); + + Status ReadVMX(); + + Status WriteVMX(); + + Status ReadVSX(); + + Status WriteVSX(); + + void *GetGPRBuffer() override { return &m_gpr_ppc64le; } + + void *GetFPRBuffer() override { return &m_fpr_ppc64le; } + + size_t GetFPRSize() override { return sizeof(m_fpr_ppc64le); } + +private: + GPR m_gpr_ppc64le; // 64-bit general purpose registers. + FPR m_fpr_ppc64le; // floating-point registers including extended register. + VMX m_vmx_ppc64le; // VMX registers. + VSX m_vsx_ppc64le; // Last lower bytes from first VSX registers. + + bool IsGPR(unsigned reg) const; + + bool IsFPR(unsigned reg) const; + + bool IsVMX(unsigned reg) const; + + bool IsVSX(unsigned reg) const; + + uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const; + + uint32_t CalculateVmxOffset(const RegisterInfo *reg_info) const; + + uint32_t CalculateVsxOffset(const RegisterInfo *reg_info) const; + + Status ReadHardwareDebugInfo(); + + Status WriteHardwareDebugRegs(); + + // Debug register info for hardware watchpoints management. + struct DREG { + lldb::addr_t address; // Breakpoint/watchpoint address value. + lldb::addr_t hit_addr; // Address at which last watchpoint trigger + // exception occurred. + lldb::addr_t real_addr; // Address value that should cause target to stop. + uint32_t control; // Breakpoint/watchpoint control value. + uint32_t refcount; // Serves as enable/disable and reference counter. + long slot; // Saves the value returned from PTRACE_SETHWDEBUG. + int mode; // Defines if watchpoint is read/write/access. + }; + + std::array<DREG, 4> m_hwp_regs; + + // 16 is just a maximum value, query hardware for actual watchpoint count + uint32_t m_max_hwp_supported = 16; + uint32_t m_max_hbp_supported = 16; + bool m_refresh_hwdebug_info = true; +}; + +} // namespace process_linux +} // namespace lldb_private + +#endif // #ifndef lldb_NativeRegisterContextLinux_ppc64le_h + +#endif // defined(__powerpc64__) diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp index c2a696e08bf94..021394ab154b5 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp @@ -97,12 +97,11 @@ static const RegisterSet g_reg_sets_s390x[k_num_register_sets] = { #define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */ #define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */ -NativeRegisterContextLinux * +std::unique_ptr<NativeRegisterContextLinux> NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) { - return new NativeRegisterContextLinux_s390x(target_arch, native_thread, - concrete_frame_idx); + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { + return llvm::make_unique<NativeRegisterContextLinux_s390x>(target_arch, + native_thread); } // ---------------------------------------------------------------------------- @@ -117,9 +116,8 @@ CreateRegisterInfoInterface(const ArchSpec &target_arch) { } NativeRegisterContextLinux_s390x::NativeRegisterContextLinux_s390x( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) - : NativeRegisterContextLinux(native_thread, concrete_frame_idx, + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) + : NativeRegisterContextLinux(native_thread, CreateRegisterInfoInterface(target_arch)) { // Set up data about ranges of valid registers. switch (target_arch.GetMachine()) { diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h index 3ffbaeeb0bba8..57b1a0481512f 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h @@ -24,8 +24,7 @@ class NativeProcessLinux; class NativeRegisterContextLinux_s390x : public NativeRegisterContextLinux { public: NativeRegisterContextLinux_s390x(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeThreadProtocol &native_thread); uint32_t GetRegisterSetCount() const override; diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp index e44e03b46b5cc..84ffe9b6e4202 100755 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp @@ -243,12 +243,11 @@ static inline unsigned int fxsr_regset(const ArchSpec &arch) { #define mask_XSTATE_BNDCFG (1ULL << 4) #define mask_XSTATE_MPX (mask_XSTATE_BNDREGS | mask_XSTATE_BNDCFG) -NativeRegisterContextLinux * +std::unique_ptr<NativeRegisterContextLinux> NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) { - return new NativeRegisterContextLinux_x86_64(target_arch, native_thread, - concrete_frame_idx); + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { + return std::unique_ptr<NativeRegisterContextLinux>( + new NativeRegisterContextLinux_x86_64(target_arch, native_thread)); } // ---------------------------------------------------------------------------- @@ -270,9 +269,8 @@ CreateRegisterInfoInterface(const ArchSpec &target_arch) { } NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) - : NativeRegisterContextLinux(native_thread, concrete_frame_idx, + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) + : NativeRegisterContextLinux(native_thread, CreateRegisterInfoInterface(target_arch)), m_xstate_type(XStateType::Invalid), m_fpr(), m_iovec(), m_ymm_set(), m_mpx_set(), m_reg_info(), m_gpr_x86_64() { @@ -334,11 +332,11 @@ NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64( // Initialize m_iovec to point to the buffer and buffer size // using the conventions of Berkeley style UIO structures, as required // by PTRACE extensions. - m_iovec.iov_base = &m_fpr.xstate.xsave; - m_iovec.iov_len = sizeof(m_fpr.xstate.xsave); + m_iovec.iov_base = &m_fpr; + m_iovec.iov_len = sizeof(m_fpr); // Clear out the FPR state. - ::memset(&m_fpr, 0, sizeof(FPR)); + ::memset(&m_fpr, 0, sizeof(m_fpr)); // Store byte offset of fctrl (i.e. first register of FPR) const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl"); @@ -441,17 +439,14 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info, if (byte_order != lldb::eByteOrderInvalid) { if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st) - reg_value.SetBytes( - m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, - reg_info->byte_size, byte_order); + reg_value.SetBytes(m_fpr.fxsave.stmm[reg - m_reg_info.first_st].bytes, + reg_info->byte_size, byte_order); if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm) - reg_value.SetBytes( - m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, - reg_info->byte_size, byte_order); + reg_value.SetBytes(m_fpr.fxsave.stmm[reg - m_reg_info.first_mm].bytes, + reg_info->byte_size, byte_order); if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm) - reg_value.SetBytes( - m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, - reg_info->byte_size, byte_order); + reg_value.SetBytes(m_fpr.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, + reg_info->byte_size, byte_order); if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) { // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes if (CopyXSTATEtoYMM(reg, byte_order)) @@ -492,7 +487,7 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info, return error; } - // Get pointer to m_fpr.xstate.fxsave variable and set the data from it. + // Get pointer to m_fpr.fxsave variable and set the data from it. // Byte offsets of all registers are calculated wrt 'UserArea' structure. // However, ReadFPR() reads fpu registers {using ptrace(PTRACE_GETFPREGS,..)} @@ -530,6 +525,22 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info, return error; } +void NativeRegisterContextLinux_x86_64::UpdateXSTATEforWrite( + uint32_t reg_index) { + XSAVE_HDR::XFeature &xstate_bv = m_fpr.xsave.header.xstate_bv; + if (IsFPR(reg_index)) { + // IsFPR considers both %st and %xmm registers as floating point, but these + // map to two features. Set both flags, just in case. + xstate_bv |= XSAVE_HDR::XFeature::FP | XSAVE_HDR::XFeature::SSE; + } else if (IsAVX(reg_index)) { + // Lower bytes of some %ymm registers are shared with %xmm registers. + xstate_bv |= XSAVE_HDR::XFeature::YMM | XSAVE_HDR::XFeature::SSE; + } else if (IsMPX(reg_index)) { + // MPX registers map to two XSAVE features. + xstate_bv |= XSAVE_HDR::XFeature::BNDREGS | XSAVE_HDR::XFeature::BNDCSR; + } +} + Status NativeRegisterContextLinux_x86_64::WriteRegister( const RegisterInfo *reg_info, const RegisterValue ®_value) { assert(reg_info && "reg_info is null"); @@ -540,25 +551,24 @@ Status NativeRegisterContextLinux_x86_64::WriteRegister( ? reg_info->name : "<unknown register>"); + UpdateXSTATEforWrite(reg_index); + if (IsGPR(reg_index)) return WriteRegisterRaw(reg_index, reg_value); if (IsFPR(reg_index) || IsAVX(reg_index) || IsMPX(reg_index)) { if (reg_info->encoding == lldb::eEncodingVector) { if (reg_index >= m_reg_info.first_st && reg_index <= m_reg_info.last_st) - ::memcpy( - m_fpr.xstate.fxsave.stmm[reg_index - m_reg_info.first_st].bytes, - reg_value.GetBytes(), reg_value.GetByteSize()); + ::memcpy(m_fpr.fxsave.stmm[reg_index - m_reg_info.first_st].bytes, + reg_value.GetBytes(), reg_value.GetByteSize()); if (reg_index >= m_reg_info.first_mm && reg_index <= m_reg_info.last_mm) - ::memcpy( - m_fpr.xstate.fxsave.stmm[reg_index - m_reg_info.first_mm].bytes, - reg_value.GetBytes(), reg_value.GetByteSize()); + ::memcpy(m_fpr.fxsave.stmm[reg_index - m_reg_info.first_mm].bytes, + reg_value.GetBytes(), reg_value.GetByteSize()); if (reg_index >= m_reg_info.first_xmm && reg_index <= m_reg_info.last_xmm) - ::memcpy( - m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes, - reg_value.GetBytes(), reg_value.GetByteSize()); + ::memcpy(m_fpr.fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes, + reg_value.GetBytes(), reg_value.GetByteSize()); if (reg_index >= m_reg_info.first_ymm && reg_index <= m_reg_info.last_ymm) { @@ -586,7 +596,7 @@ Status NativeRegisterContextLinux_x86_64::WriteRegister( return Status("CopyMPXtoXSTATE() failed"); } } else { - // Get pointer to m_fpr.xstate.fxsave variable and set the data to it. + // Get pointer to m_fpr.fxsave variable and set the data to it. // Byte offsets of all registers are calculated wrt 'UserArea' structure. // However, WriteFPR() takes m_fpr (of type FPR structure) and writes only @@ -658,7 +668,7 @@ Status NativeRegisterContextLinux_x86_64::ReadAllRegisterValues( ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize()); dst += GetRegisterInfoInterface().GetGPRSize(); if (m_xstate_type == XStateType::FXSAVE) - ::memcpy(dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave)); + ::memcpy(dst, &m_fpr.fxsave, sizeof(m_fpr.fxsave)); else if (m_xstate_type == XStateType::XSAVE) { lldb::ByteOrder byte_order = GetByteOrder(); @@ -749,9 +759,9 @@ Status NativeRegisterContextLinux_x86_64::WriteAllRegisterValues( src += GetRegisterInfoInterface().GetGPRSize(); if (m_xstate_type == XStateType::FXSAVE) - ::memcpy(&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave)); + ::memcpy(&m_fpr.fxsave, src, sizeof(m_fpr.fxsave)); else if (m_xstate_type == XStateType::XSAVE) - ::memcpy(&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave)); + ::memcpy(&m_fpr.xsave, src, sizeof(m_fpr.xsave)); error = WriteFPR(); if (error.Fail()) @@ -805,12 +815,12 @@ bool NativeRegisterContextLinux_x86_64::IsCPUFeatureAvailable( return true; case RegSet::avx: // Check if CPU has AVX and if there is kernel support, by // reading in the XCR0 area of XSAVE. - if ((m_fpr.xstate.xsave.i387.xcr0 & mask_XSTATE_AVX) == mask_XSTATE_AVX) + if ((m_fpr.xsave.i387.xcr0 & mask_XSTATE_AVX) == mask_XSTATE_AVX) return true; break; case RegSet::mpx: // Check if CPU has MPX and if there is kernel support, by // reading in the XCR0 area of XSAVE. - if ((m_fpr.xstate.xsave.i387.xcr0 & mask_XSTATE_MPX) == mask_XSTATE_MPX) + if ((m_fpr.xsave.i387.xcr0 & mask_XSTATE_MPX) == mask_XSTATE_MPX) return true; break; } @@ -847,11 +857,10 @@ Status NativeRegisterContextLinux_x86_64::WriteFPR() { switch (m_xstate_type) { case XStateType::FXSAVE: return WriteRegisterSet( - &m_iovec, sizeof(m_fpr.xstate.xsave), + &m_iovec, sizeof(m_fpr.fxsave), fxsr_regset(GetRegisterInfoInterface().GetTargetArchitecture())); case XStateType::XSAVE: - return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), - NT_X86_XSTATE); + return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xsave), NT_X86_XSTATE); default: return Status("Unrecognized FPR type."); } @@ -871,11 +880,11 @@ bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM( if (byte_order == lldb::eByteOrderLittle) { ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes, - m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes, + m_fpr.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes, sizeof(XMMReg)); ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes + sizeof(XMMReg), - m_fpr.xstate.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes, + m_fpr.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes, sizeof(YMMHReg)); return true; } @@ -883,10 +892,10 @@ bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM( if (byte_order == lldb::eByteOrderBig) { ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes + sizeof(XMMReg), - m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes, + m_fpr.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes, sizeof(XMMReg)); ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes, - m_fpr.xstate.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes, + m_fpr.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes, sizeof(YMMHReg)); return true; } @@ -899,19 +908,19 @@ bool NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE( return false; if (byte_order == lldb::eByteOrderLittle) { - ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + ::memcpy(m_fpr.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(XMMReg)); - ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + ::memcpy(m_fpr.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), sizeof(YMMHReg)); return true; } if (byte_order == lldb::eByteOrderBig) { - ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + ::memcpy(m_fpr.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), sizeof(XMMReg)); - ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + ::memcpy(m_fpr.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(YMMHReg)); return true; } @@ -921,7 +930,7 @@ bool NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE( void *NativeRegisterContextLinux_x86_64::GetFPRBuffer() { switch (m_xstate_type) { case XStateType::FXSAVE: - return &m_fpr.xstate.fxsave; + return &m_fpr.fxsave; case XStateType::XSAVE: return &m_iovec; default: @@ -932,7 +941,7 @@ void *NativeRegisterContextLinux_x86_64::GetFPRBuffer() { size_t NativeRegisterContextLinux_x86_64::GetFPRSize() { switch (m_xstate_type) { case XStateType::FXSAVE: - return sizeof(m_fpr.xstate.fxsave); + return sizeof(m_fpr.fxsave); case XStateType::XSAVE: return sizeof(m_iovec); default: @@ -945,15 +954,14 @@ Status NativeRegisterContextLinux_x86_64::ReadFPR() { // Probe XSAVE and if it is not supported fall back to FXSAVE. if (m_xstate_type != XStateType::FXSAVE) { - error = - ReadRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); + error = ReadRegisterSet(&m_iovec, sizeof(m_fpr.xsave), NT_X86_XSTATE); if (!error.Fail()) { m_xstate_type = XStateType::XSAVE; return error; } } error = ReadRegisterSet( - &m_iovec, sizeof(m_fpr.xstate.xsave), + &m_iovec, sizeof(m_fpr.xsave), fxsr_regset(GetRegisterInfoInterface().GetTargetArchitecture())); if (!error.Fail()) { m_xstate_type = XStateType::FXSAVE; @@ -975,11 +983,11 @@ bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoMPX(uint32_t reg) { if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) { ::memcpy(m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes, - m_fpr.xstate.xsave.mpxr[reg - m_reg_info.first_mpxr].bytes, + m_fpr.xsave.mpxr[reg - m_reg_info.first_mpxr].bytes, sizeof(MPXReg)); } else { ::memcpy(m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes, - m_fpr.xstate.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes, + m_fpr.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes, sizeof(MPXCsr)); } return true; @@ -990,10 +998,10 @@ bool NativeRegisterContextLinux_x86_64::CopyMPXtoXSTATE(uint32_t reg) { return false; if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) { - ::memcpy(m_fpr.xstate.xsave.mpxr[reg - m_reg_info.first_mpxr].bytes, + ::memcpy(m_fpr.xsave.mpxr[reg - m_reg_info.first_mpxr].bytes, m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes, sizeof(MPXReg)); } else { - ::memcpy(m_fpr.xstate.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes, + ::memcpy(m_fpr.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes, m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes, sizeof(MPXCsr)); } return true; diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h index abb0dba4d91ca..9dcf82f50a458 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h @@ -15,6 +15,7 @@ #include "Plugins/Process/Linux/NativeRegisterContextLinux.h" #include "Plugins/Process/Utility/RegisterContext_x86.h" #include "Plugins/Process/Utility/lldb-x86-register-enums.h" +#include <sys/uio.h> namespace lldb_private { namespace process_linux { @@ -24,8 +25,7 @@ class NativeProcessLinux; class NativeRegisterContextLinux_x86_64 : public NativeRegisterContextLinux { public: NativeRegisterContextLinux_x86_64(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeThreadProtocol &native_thread); uint32_t GetRegisterSetCount() const override; @@ -110,7 +110,7 @@ private: // Private member variables. mutable XStateType m_xstate_type; FPR m_fpr; // Extended States Area, named FPR for historical reasons. - IOVEC m_iovec; + struct iovec m_iovec; YMM m_ymm_set; MPX m_mpx_set; RegInfo m_reg_info; @@ -137,6 +137,8 @@ private: bool CopyMPXtoXSTATE(uint32_t reg); bool IsMPX(uint32_t reg_index) const; + + void UpdateXSTATEforWrite(uint32_t reg_index); }; } // namespace process_linux diff --git a/source/Plugins/Process/Linux/NativeThreadLinux.cpp b/source/Plugins/Process/Linux/NativeThreadLinux.cpp index 5cd40941dcf8e..0db3bd56b8e4c 100644 --- a/source/Plugins/Process/Linux/NativeThreadLinux.cpp +++ b/source/Plugins/Process/Linux/NativeThreadLinux.cpp @@ -88,7 +88,11 @@ void LogThreadStopInfo(Log &log, const ThreadStopInfo &stop_info, NativeThreadLinux::NativeThreadLinux(NativeProcessLinux &process, lldb::tid_t tid) : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid), - m_stop_info(), m_reg_context_sp(), m_stop_description() {} + m_stop_info(), + m_reg_context_up( + NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( + process.GetArchitecture(), *this)), + m_stop_description() {} std::string NativeThreadLinux::GetName() { NativeProcessLinux &process = GetProcess(); @@ -139,23 +143,6 @@ bool NativeThreadLinux::GetStopReason(ThreadStopInfo &stop_info, llvm_unreachable("unhandled StateType!"); } -NativeRegisterContextSP NativeThreadLinux::GetRegisterContext() { - // Return the register context if we already created it. - if (m_reg_context_sp) - return m_reg_context_sp; - - ArchSpec target_arch; - if (!m_process.GetArchitecture(target_arch)) - return NativeRegisterContextSP(); - - const uint32_t concrete_frame_idx = 0; - m_reg_context_sp.reset( - NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( - target_arch, *this, concrete_frame_idx)); - - return m_reg_context_sp; -} - Status NativeThreadLinux::SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) { if (!hardware) @@ -165,8 +152,8 @@ Status NativeThreadLinux::SetWatchpoint(lldb::addr_t addr, size_t size, Status error = RemoveWatchpoint(addr); if (error.Fail()) return error; - NativeRegisterContextSP reg_ctx = GetRegisterContext(); - uint32_t wp_index = reg_ctx->SetHardwareWatchpoint(addr, size, watch_flags); + uint32_t wp_index = + m_reg_context_up->SetHardwareWatchpoint(addr, size, watch_flags); if (wp_index == LLDB_INVALID_INDEX32) return Status("Setting hardware watchpoint failed."); m_watchpoint_index_map.insert({addr, wp_index}); @@ -179,7 +166,7 @@ Status NativeThreadLinux::RemoveWatchpoint(lldb::addr_t addr) { return Status(); uint32_t wp_index = wp->second; m_watchpoint_index_map.erase(wp); - if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index)) + if (m_reg_context_up->ClearHardwareWatchpoint(wp_index)) return Status(); return Status("Clearing hardware watchpoint failed."); } @@ -193,8 +180,7 @@ Status NativeThreadLinux::SetHardwareBreakpoint(lldb::addr_t addr, if (error.Fail()) return error; - NativeRegisterContextSP reg_ctx = GetRegisterContext(); - uint32_t bp_index = reg_ctx->SetHardwareBreakpoint(addr, size); + uint32_t bp_index = m_reg_context_up->SetHardwareBreakpoint(addr, size); if (bp_index == LLDB_INVALID_INDEX32) return Status("Setting hardware breakpoint failed."); @@ -209,7 +195,7 @@ Status NativeThreadLinux::RemoveHardwareBreakpoint(lldb::addr_t addr) { return Status(); uint32_t bp_index = bp->second; - if (GetRegisterContext()->ClearHardwareBreakpoint(bp_index)) { + if (m_reg_context_up->ClearHardwareBreakpoint(bp_index)) { m_hw_break_index_map.erase(bp); return Status(); } @@ -231,7 +217,7 @@ Status NativeThreadLinux::Resume(uint32_t signo) { NativeProcessLinux &process = GetProcess(); const auto &watchpoint_map = process.GetWatchpointMap(); - GetRegisterContext()->ClearAllHardwareWatchpoints(); + m_reg_context_up->ClearAllHardwareWatchpoints(); for (const auto &pair : watchpoint_map) { const auto &wp = pair.second; SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, wp.m_hardware); @@ -243,7 +229,7 @@ Status NativeThreadLinux::Resume(uint32_t signo) { NativeProcessLinux &process = GetProcess(); const auto &hw_breakpoint_map = process.GetHardwareBreakpointMap(); - GetRegisterContext()->ClearAllHardwareBreakpoints(); + m_reg_context_up->ClearAllHardwareBreakpoints(); for (const auto &pair : hw_breakpoint_map) { const auto &bp = pair.second; SetHardwareBreakpoint(bp.m_addr, bp.m_size); @@ -365,7 +351,7 @@ void NativeThreadLinux::SetStoppedByWatchpoint(uint32_t wp_index) { lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid"); std::ostringstream ostr; - ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " "; + ostr << m_reg_context_up->GetWatchpointAddress(wp_index) << " "; ostr << wp_index; /* @@ -379,7 +365,7 @@ void NativeThreadLinux::SetStoppedByWatchpoint(uint32_t wp_index) { * stop-info * packet. */ - ostr << " " << GetRegisterContext()->GetWatchpointHitAddress(wp_index); + ostr << " " << m_reg_context_up->GetWatchpointHitAddress(wp_index); m_stop_description = ostr.str(); diff --git a/source/Plugins/Process/Linux/NativeThreadLinux.h b/source/Plugins/Process/Linux/NativeThreadLinux.h index 6ae87feffcda8..a7c4e982012d2 100644 --- a/source/Plugins/Process/Linux/NativeThreadLinux.h +++ b/source/Plugins/Process/Linux/NativeThreadLinux.h @@ -10,7 +10,8 @@ #ifndef liblldb_NativeThreadLinux_H_ #define liblldb_NativeThreadLinux_H_ -#include "SingleStepCheck.h" +#include "Plugins/Process/Linux/NativeRegisterContextLinux.h" +#include "Plugins/Process/Linux/SingleStepCheck.h" #include "lldb/Host/common/NativeThreadProtocol.h" #include "lldb/lldb-private-forward.h" @@ -40,7 +41,9 @@ public: bool GetStopReason(ThreadStopInfo &stop_info, std::string &description) override; - NativeRegisterContextSP GetRegisterContext() override; + NativeRegisterContextLinux &GetRegisterContext() override { + return *m_reg_context_up; + } Status SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) override; @@ -103,15 +106,13 @@ private: // --------------------------------------------------------------------- lldb::StateType m_state; ThreadStopInfo m_stop_info; - NativeRegisterContextSP m_reg_context_sp; + std::unique_ptr<NativeRegisterContextLinux> m_reg_context_up; std::string m_stop_description; using WatchpointIndexMap = std::map<lldb::addr_t, uint32_t>; WatchpointIndexMap m_watchpoint_index_map; WatchpointIndexMap m_hw_break_index_map; std::unique_ptr<SingleStepWorkaround> m_step_workaround; }; - -typedef std::shared_ptr<NativeThreadLinux> NativeThreadLinuxSP; } // namespace process_linux } // namespace lldb_private diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h index 52b9441e0e792..b4eae58af83cc 100644 --- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h +++ b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h @@ -17,12 +17,12 @@ #include <vector> // Other libraries and framework includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Broadcaster.h" #include "lldb/Core/ThreadSafeValue.h" #include "lldb/Host/HostThread.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" diff --git a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp index ae2f11f380061..1902cc492ff4f 100644 --- a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp +++ b/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp @@ -12,13 +12,13 @@ #include "lldb/Utility/SafeMachO.h" #include "lldb/Breakpoint/Watchpoint.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/State.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/Unwind.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/StreamString.h" diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp index 388989a21f767..387f04afa5b46 100644 --- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp +++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp @@ -109,10 +109,8 @@ NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info, if (status.Fail()) return status.ToError(); - for (const auto &thread_sp : process_up->m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal( - SIGSTOP); - } + for (const auto &thread : process_up->m_threads) + static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP); process_up->SetState(StateType::eStateStopped); return std::move(process_up); @@ -198,9 +196,9 @@ void NativeProcessNetBSD::MonitorSIGSTOP(lldb::pid_t pid) { // Handle SIGSTOP from LLGS (LLDB GDB Server) if (info.psi_siginfo.si_code == SI_USER && info.psi_siginfo.si_pid == ::getpid()) { - /* Stop Tracking All Threads attached to Process */ - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal( + /* Stop Tracking all Threads attached to Process */ + for (const auto &thread : m_threads) { + static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal( SIGSTOP, &info.psi_siginfo); } } @@ -221,18 +219,15 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) { switch (info.psi_siginfo.si_code) { case TRAP_BRKPT: - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp) - ->SetStoppedByBreakpoint(); - FixupBreakpointPCAsNeeded( - *static_pointer_cast<NativeThreadNetBSD>(thread_sp)); + for (const auto &thread : m_threads) { + static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByBreakpoint(); + FixupBreakpointPCAsNeeded(static_cast<NativeThreadNetBSD &>(*thread)); } SetState(StateType::eStateStopped, true); break; case TRAP_TRACE: - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedByTrace(); - } + for (const auto &thread : m_threads) + static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByTrace(); SetState(StateType::eStateStopped, true); break; case TRAP_EXEC: { @@ -245,38 +240,35 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) { // Let our delegate know we have just exec'd. NotifyDidExec(); - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedByExec(); - } + for (const auto &thread : m_threads) + static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByExec(); SetState(StateType::eStateStopped, true); } break; case TRAP_DBREG: { // If a watchpoint was hit, report it uint32_t wp_index; - Status error = - static_pointer_cast<NativeThreadNetBSD>(m_threads[info.psi_lwpid]) - ->GetRegisterContext() - ->GetWatchpointHitIndex(wp_index, - (uintptr_t)info.psi_siginfo.si_addr); + Status error = static_cast<NativeThreadNetBSD &>(*m_threads[info.psi_lwpid]) + .GetRegisterContext() + .GetWatchpointHitIndex( + wp_index, (uintptr_t)info.psi_siginfo.si_addr); if (error.Fail()) LLDB_LOG(log, "received error while checking for watchpoint hits, pid = " "{0}, LWP = {1}, error = {2}", GetID(), info.psi_lwpid, error); if (wp_index != LLDB_INVALID_INDEX32) { - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp) - ->SetStoppedByWatchpoint(wp_index); - } + for (const auto &thread : m_threads) + static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByWatchpoint( + wp_index); SetState(StateType::eStateStopped, true); break; } // If a breakpoint was hit, report it uint32_t bp_index; - error = static_pointer_cast<NativeThreadNetBSD>(m_threads[info.psi_lwpid]) - ->GetRegisterContext() - ->GetHardwareBreakHitIndex(bp_index, + error = static_cast<NativeThreadNetBSD &>(*m_threads[info.psi_lwpid]) + .GetRegisterContext() + .GetHardwareBreakHitIndex(bp_index, (uintptr_t)info.psi_siginfo.si_addr); if (error.Fail()) LLDB_LOG(log, @@ -284,10 +276,8 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) { "breakpoint hits, pid = {0}, LWP = {1}, error = {2}", GetID(), info.psi_lwpid, error); if (bp_index != LLDB_INVALID_INDEX32) { - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp) - ->SetStoppedByBreakpoint(); - } + for (const auto &thread : m_threads) + static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByBreakpoint(); SetState(StateType::eStateStopped, true); break; } @@ -300,8 +290,8 @@ void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) { const auto siginfo_err = PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info)); - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal( + for (const auto &thread : m_threads) { + static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal( info.psi_siginfo.si_signo, &info.psi_siginfo); } SetState(StateType::eStateStopped, true); @@ -351,12 +341,7 @@ NativeProcessNetBSD::FixupBreakpointPCAsNeeded(NativeThreadNetBSD &thread) { Status error; // Find out the size of a breakpoint (might depend on where we are in the // code). - NativeRegisterContextSP context_sp = thread.GetRegisterContext(); - if (!context_sp) { - error.SetErrorString("cannot get a NativeRegisterContext for the thread"); - LLDB_LOG(log, "failed: {0}", error); - return error; - } + NativeRegisterContext& context = thread.GetRegisterContext(); uint32_t breakpoint_size = 0; error = GetSoftwareBreakpointPCOffset(breakpoint_size); if (error.Fail()) { @@ -367,7 +352,7 @@ NativeProcessNetBSD::FixupBreakpointPCAsNeeded(NativeThreadNetBSD &thread) { // First try probing for a breakpoint at a software breakpoint location: PC // - breakpoint size. const lldb::addr_t initial_pc_addr = - context_sp->GetPCfromBreakpointLocation(); + context.GetPCfromBreakpointLocation(); lldb::addr_t breakpoint_addr = initial_pc_addr; if (breakpoint_size > 0) { // Do not allow breakpoint probe to wrap around. @@ -420,7 +405,7 @@ NativeProcessNetBSD::FixupBreakpointPCAsNeeded(NativeThreadNetBSD &thread) { // Change the program counter. LLDB_LOG(log, "pid {0} tid {1}: changing PC from {2:x} to {3:x}", GetID(), thread.GetID(), initial_pc_addr, breakpoint_addr); - error = context_sp->SetPC(breakpoint_addr); + error = context.SetPC(breakpoint_addr); if (error.Fail()) { LLDB_LOG(log, "pid {0} tid {1}: failed to set PC: {2}", GetID(), thread.GetID(), error); @@ -433,13 +418,13 @@ Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); LLDB_LOG(log, "pid {0}", GetID()); - const auto &thread_sp = m_threads[0]; + const auto &thread = m_threads[0]; const ResumeAction *const action = - resume_actions.GetActionForThread(thread_sp->GetID(), true); + resume_actions.GetActionForThread(thread->GetID(), true); if (action == nullptr) { LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(), - thread_sp->GetID()); + thread->GetID()); return Status(); } @@ -452,9 +437,8 @@ Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) { action->signal); if (!error.Success()) return error; - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetRunning(); - } + for (const auto &thread : m_threads) + static_cast<NativeThreadNetBSD &>(*thread).SetRunning(); SetState(eStateRunning, true); break; } @@ -464,9 +448,8 @@ Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) { action->signal); if (!error.Success()) return error; - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStepping(); - } + for (const auto &thread : m_threads) + static_cast<NativeThreadNetBSD &>(*thread).SetStepping(); SetState(eStateStepping, true); break; @@ -478,7 +461,7 @@ Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) { return Status("NativeProcessNetBSD::%s (): unexpected state %s specified " "for pid %" PRIu64 ", tid %" PRIu64, __FUNCTION__, StateAsCString(action->state), GetID(), - thread_sp->GetID()); + thread->GetID()); } return Status(); @@ -690,11 +673,6 @@ lldb::addr_t NativeProcessNetBSD::GetSharedLibraryInfoAddress() { size_t NativeProcessNetBSD::UpdateThreads() { return m_threads.size(); } -bool NativeProcessNetBSD::GetArchitecture(ArchSpec &arch) const { - arch = m_arch; - return true; -} - Status NativeProcessNetBSD::SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) { if (hardware) @@ -764,9 +742,9 @@ void NativeProcessNetBSD::SigchldHandler() { } bool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id) { - for (auto thread_sp : m_threads) { - assert(thread_sp && "thread list should not contain NULL threads"); - if (thread_sp->GetID() == thread_id) { + for (const auto &thread : m_threads) { + assert(thread && "thread list should not contain NULL threads"); + if (thread->GetID() == thread_id) { // We have this thread. return true; } @@ -776,7 +754,7 @@ bool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id) { return false; } -NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) { +NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id); @@ -788,9 +766,8 @@ NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) { if (m_threads.empty()) SetCurrentThreadID(thread_id); - auto thread_sp = std::make_shared<NativeThreadNetBSD>(*this, thread_id); - m_threads.push_back(thread_sp); - return thread_sp; + m_threads.push_back(llvm::make_unique<NativeThreadNetBSD>(*this, thread_id)); + return static_cast<NativeThreadNetBSD &>(*m_threads.back()); } Status NativeProcessNetBSD::Attach() { @@ -811,10 +788,8 @@ Status NativeProcessNetBSD::Attach() { if (status.Fail()) return status; - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal( - SIGSTOP); - } + for (const auto &thread : m_threads) + static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP); // Let our process instance know the thread has stopped. SetState(StateType::eStateStopped); @@ -928,7 +903,7 @@ Status NativeProcessNetBSD::ReinitializeThreads() { } // Reinitialize from scratch threads and register them in process while (info.pl_lwpid != 0) { - NativeThreadNetBSDSP thread_sp = AddThread(info.pl_lwpid); + AddThread(info.pl_lwpid); error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info)); if (error.Fail()) { return error; diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h index 2cbd5e30ab23b..7090fce34fc9c 100644 --- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h +++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h @@ -10,12 +10,8 @@ #ifndef liblldb_NativeProcessNetBSD_H_ #define liblldb_NativeProcessNetBSD_H_ -// C++ Includes - -// Other libraries and framework includes - -#include "lldb/Core/ArchSpec.h" #include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/FileSpec.h" #include "NativeThreadNetBSD.h" @@ -77,7 +73,7 @@ public: size_t UpdateThreads() override; - bool GetArchitecture(ArchSpec &arch) const override; + const ArchSpec &GetArchitecture() const override { return m_arch; } Status SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) override; @@ -121,7 +117,7 @@ private: bool HasThreadNoLock(lldb::tid_t thread_id); - NativeThreadNetBSDSP AddThread(lldb::tid_t thread_id); + NativeThreadNetBSD &AddThread(lldb::tid_t thread_id); void MonitorCallback(lldb::pid_t pid, int signal); void MonitorExited(lldb::pid_t pid, WaitStatus status); diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp index dde86880c41a1..d4fef6342439d 100644 --- a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp +++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp @@ -20,9 +20,9 @@ using namespace lldb_private::process_netbsd; // clang-format on NativeRegisterContextNetBSD::NativeRegisterContextNetBSD( - NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx, + NativeThreadProtocol &native_thread, RegisterInfoInterface *reg_info_interface_p) - : NativeRegisterContextRegisterInfo(native_thread, concrete_frame_idx, + : NativeRegisterContextRegisterInfo(native_thread, reg_info_interface_p) {} Status NativeRegisterContextNetBSD::ReadGPR() { diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h index d96b7aea00486..b81430e7f5acf 100644 --- a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h +++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h @@ -21,7 +21,6 @@ namespace process_netbsd { class NativeRegisterContextNetBSD : public NativeRegisterContextRegisterInfo { public: NativeRegisterContextNetBSD(NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx, RegisterInfoInterface *reg_info_interface_p); // This function is implemented in the NativeRegisterContextNetBSD_* @@ -31,8 +30,7 @@ public: // executable. static NativeRegisterContextNetBSD * CreateHostNativeRegisterContextNetBSD(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeThreadProtocol &native_thread); protected: virtual Status ReadGPR(); diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp index 9690da0e1374f..347c15ae5b239 100644 --- a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp +++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp @@ -149,10 +149,8 @@ const int fpu_save = []() -> int { NativeRegisterContextNetBSD * NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) { - return new NativeRegisterContextNetBSD_x86_64(target_arch, native_thread, - concrete_frame_idx); + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { + return new NativeRegisterContextNetBSD_x86_64(target_arch, native_thread); } // ---------------------------------------------------------------------------- @@ -169,9 +167,8 @@ CreateRegisterInfoInterface(const ArchSpec &target_arch) { } NativeRegisterContextNetBSD_x86_64::NativeRegisterContextNetBSD_x86_64( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) - : NativeRegisterContextNetBSD(native_thread, concrete_frame_idx, + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) + : NativeRegisterContextNetBSD(native_thread, CreateRegisterInfoInterface(target_arch)), m_gpr_x86_64(), m_fpr_x86_64(), m_dbr_x86_64() {} diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h index 5f5a6a0792e4d..c55ddfec66156 100644 --- a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h +++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h @@ -30,8 +30,7 @@ class NativeProcessNetBSD; class NativeRegisterContextNetBSD_x86_64 : public NativeRegisterContextNetBSD { public: NativeRegisterContextNetBSD_x86_64(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeThreadProtocol &native_thread); uint32_t GetRegisterSetCount() const override; const RegisterSet *GetRegisterSet(uint32_t set_index) const override; diff --git a/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp index 1fd7400bf800c..83f1da78d01d0 100644 --- a/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp +++ b/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp @@ -27,7 +27,9 @@ using namespace lldb_private::process_netbsd; NativeThreadNetBSD::NativeThreadNetBSD(NativeProcessNetBSD &process, lldb::tid_t tid) : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid), - m_stop_info(), m_reg_context_sp(), m_stop_description() {} + m_stop_info(), m_reg_context_up( +NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD(process.GetArchitecture(), *this) +), m_stop_description() {} void NativeThreadNetBSD::SetStoppedBySignal(uint32_t signo, const siginfo_t *info) { @@ -77,10 +79,10 @@ void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) { lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid"); std::ostringstream ostr; - ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " "; + ostr << GetRegisterContext().GetWatchpointAddress(wp_index) << " "; ostr << wp_index; - ostr << " " << GetRegisterContext()->GetWatchpointHitAddress(wp_index); + ostr << " " << GetRegisterContext().GetWatchpointHitAddress(wp_index); m_stop_description = ostr.str(); @@ -139,21 +141,9 @@ bool NativeThreadNetBSD::GetStopReason(ThreadStopInfo &stop_info, llvm_unreachable("unhandled StateType!"); } -NativeRegisterContextSP NativeThreadNetBSD::GetRegisterContext() { - // Return the register context if we already created it. - if (m_reg_context_sp) - return m_reg_context_sp; - - ArchSpec target_arch; - if (!m_process.GetArchitecture(target_arch)) - return NativeRegisterContextSP(); - - const uint32_t concrete_frame_idx = 0; - m_reg_context_sp.reset( - NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD( - target_arch, *this, concrete_frame_idx)); - - return m_reg_context_sp; +NativeRegisterContext& NativeThreadNetBSD::GetRegisterContext() { + assert(m_reg_context_up); +return *m_reg_context_up; } Status NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size, @@ -165,8 +155,7 @@ Status NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size, Status error = RemoveWatchpoint(addr); if (error.Fail()) return error; - NativeRegisterContextSP reg_ctx = GetRegisterContext(); - uint32_t wp_index = reg_ctx->SetHardwareWatchpoint(addr, size, watch_flags); + uint32_t wp_index = GetRegisterContext().SetHardwareWatchpoint(addr, size, watch_flags); if (wp_index == LLDB_INVALID_INDEX32) return Status("Setting hardware watchpoint failed."); m_watchpoint_index_map.insert({addr, wp_index}); @@ -179,7 +168,7 @@ Status NativeThreadNetBSD::RemoveWatchpoint(lldb::addr_t addr) { return Status(); uint32_t wp_index = wp->second; m_watchpoint_index_map.erase(wp); - if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index)) + if (GetRegisterContext().ClearHardwareWatchpoint(wp_index)) return Status(); return Status("Clearing hardware watchpoint failed."); } @@ -193,8 +182,7 @@ Status NativeThreadNetBSD::SetHardwareBreakpoint(lldb::addr_t addr, if (error.Fail()) return error; - NativeRegisterContextSP reg_ctx = GetRegisterContext(); - uint32_t bp_index = reg_ctx->SetHardwareBreakpoint(addr, size); + uint32_t bp_index = GetRegisterContext().SetHardwareBreakpoint(addr, size); if (bp_index == LLDB_INVALID_INDEX32) return Status("Setting hardware breakpoint failed."); @@ -209,7 +197,7 @@ Status NativeThreadNetBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) { return Status(); uint32_t bp_index = bp->second; - if (GetRegisterContext()->ClearHardwareBreakpoint(bp_index)) { + if (GetRegisterContext().ClearHardwareBreakpoint(bp_index)) { m_hw_break_index_map.erase(bp); return Status(); } diff --git a/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h b/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h index 1e3f587be5f5b..72426244c1127 100644 --- a/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h +++ b/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h @@ -37,7 +37,7 @@ public: bool GetStopReason(ThreadStopInfo &stop_info, std::string &description) override; - NativeRegisterContextSP GetRegisterContext() override; + NativeRegisterContext& GetRegisterContext() override; Status SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) override; @@ -67,7 +67,7 @@ private: // --------------------------------------------------------------------- lldb::StateType m_state; ThreadStopInfo m_stop_info; - NativeRegisterContextSP m_reg_context_sp; + std::unique_ptr<NativeRegisterContext> m_reg_context_up; std::string m_stop_description; using WatchpointIndexMap = std::map<lldb::addr_t, uint32_t>; WatchpointIndexMap m_watchpoint_index_map; diff --git a/source/Plugins/Process/Utility/CMakeLists.txt b/source/Plugins/Process/Utility/CMakeLists.txt index bda0ad626f6f8..3780fb5e4c18d 100644 --- a/source/Plugins/Process/Utility/CMakeLists.txt +++ b/source/Plugins/Process/Utility/CMakeLists.txt @@ -39,11 +39,13 @@ add_lldb_library(lldbPluginProcessUtility PLUGIN RegisterContextPOSIX_arm64.cpp RegisterContextPOSIX_mips64.cpp RegisterContextPOSIX_powerpc.cpp + RegisterContextPOSIX_ppc64le.cpp RegisterContextPOSIX_s390x.cpp RegisterContextPOSIX_x86.cpp RegisterContextThreadMemory.cpp RegisterInfoPOSIX_arm.cpp RegisterInfoPOSIX_arm64.cpp + RegisterInfoPOSIX_ppc64le.cpp StopInfoMachException.cpp ThreadMemory.cpp UnwindLLDB.cpp diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp index 1a4511a822309..61e5bf4481d6a 100644 --- a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -9,14 +9,10 @@ #include "DynamicRegisterInfo.h" -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/StreamFile.h" #include "lldb/DataFormatters/FormatManager.h" #include "lldb/Host/StringConvert.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/StringExtractor.h" #include "lldb/Utility/StructuredData.h" diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp index 4e1f10c6ae181..5c51a035ec665 100644 --- a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp +++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp @@ -64,7 +64,7 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, options.SetTimeout(std::chrono::milliseconds(500)); options.SetTrapExceptions(false); - addr_t prot_arg, flags_arg = 0; + addr_t prot_arg; if (prot == eMmapProtNone) prot_arg = PROT_NONE; else { @@ -77,11 +77,6 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, prot_arg |= PROT_WRITE; } - const ArchSpec arch = process->GetTarget().GetArchitecture(); - flags_arg = - process->GetTarget().GetPlatform()->ConvertMmapFlagsToPlatform(arch, - flags); - AddressRange mmap_range; if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range)) { @@ -89,7 +84,10 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, process->GetTarget().GetScratchClangASTContext(); CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - lldb::addr_t args[] = {addr, length, prot_arg, flags_arg, fd, offset}; + const ArchSpec arch = process->GetTarget().GetArchitecture(); + MmapArgList args = + process->GetTarget().GetPlatform()->GetMmapArgumentList( + arch, addr, length, prot_arg, flags, fd, offset); lldb::ThreadPlanSP call_plan_sp( new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(), clang_void_ptr_type, args, options)); diff --git a/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.cpp b/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.cpp index 0b18143624255..3a9d497711c0f 100644 --- a/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.cpp +++ b/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.cpp @@ -14,9 +14,9 @@ using namespace lldb_private; NativeRegisterContextRegisterInfo::NativeRegisterContextRegisterInfo( - NativeThreadProtocol &thread, uint32_t concrete_frame_idx, + NativeThreadProtocol &thread, RegisterInfoInterface *register_info_interface) - : NativeRegisterContext(thread, concrete_frame_idx), + : NativeRegisterContext(thread), m_register_info_interface_up(register_info_interface) { assert(register_info_interface && "null register_info_interface"); } diff --git a/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h b/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h index c1b597462b60a..8f2e4409105fa 100644 --- a/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h +++ b/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h @@ -23,7 +23,7 @@ public: /// of the register_info_interface pointer. /// NativeRegisterContextRegisterInfo( - NativeThreadProtocol &thread, uint32_t concrete_frame_idx, + NativeThreadProtocol &thread, RegisterInfoInterface *register_info_interface); uint32_t GetRegisterCount() const override; diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp index 0c36f1a8346cd..344c08965fad5 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp @@ -426,7 +426,7 @@ bool RegisterContextDarwin_arm64::ReadRegister(const RegisterInfo *reg_info, case fpu_v29: case fpu_v30: case fpu_v31: - value.SetBytes(fpu.v[reg].bytes, reg_info->byte_size, + value.SetBytes(fpu.v[reg].bytes.buffer, reg_info->byte_size, endian::InlHostByteOrder()); break; @@ -618,7 +618,7 @@ bool RegisterContextDarwin_arm64::WriteRegister(const RegisterInfo *reg_info, case fpu_v29: case fpu_v30: case fpu_v31: - ::memcpy(fpu.v[reg].bytes, value.GetBytes(), value.GetByteSize()); + ::memcpy(fpu.v[reg].bytes.buffer, value.GetBytes(), value.GetByteSize()); break; case fpu_fpsr: diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h index 2d1fe0555b58f..4a0e50947ee70 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h @@ -78,7 +78,7 @@ public: }; struct VReg { - uint8_t bytes[16]; + llvm::AlignedCharArray<16, 16> bytes; }; // mirrors <mach/arm/thread_status.h> arm_neon_state64_t diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index bd73a29e08713..5435a02433aba 100644 --- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -1517,8 +1517,8 @@ RegisterContextLLDB::SavedLocationForRegister( dwarfexpr.SetRegisterKind(unwindplan_registerkind); Value result; Status error; - if (dwarfexpr.Evaluate(&exe_ctx, nullptr, nullptr, this, 0, nullptr, - nullptr, result, &error)) { + if (dwarfexpr.Evaluate(&exe_ctx, this, 0, nullptr, nullptr, result, + &error)) { addr_t val; val = result.GetScalar().ULongLong(); if (unwindplan_regloc.IsDWARFExpression()) { @@ -1827,8 +1827,8 @@ bool RegisterContextLLDB::ReadCFAValueForRow( dwarfexpr.SetRegisterKind(row_register_kind); Value result; Status error; - if (dwarfexpr.Evaluate(&exe_ctx, nullptr, nullptr, this, 0, nullptr, - nullptr, result, &error)) { + if (dwarfexpr.Evaluate(&exe_ctx, this, 0, nullptr, nullptr, result, + &error)) { cfa_value = result.GetScalar().ULongLong(); UnwindLogMsg("CFA value set by DWARF expression is 0x%" PRIx64, diff --git a/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp b/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp index a4cf077101946..71d35bbd3938e 100644 --- a/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp +++ b/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp @@ -50,22 +50,30 @@ int RegisterContextMach_arm::DoReadDBG(lldb::tid_t tid, int flavor, DBG &dbg) { int RegisterContextMach_arm::DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) { - return ::thread_set_state(tid, flavor, (thread_state_t)&gpr, GPRWordCount); + return ::thread_set_state( + tid, flavor, reinterpret_cast<thread_state_t>(const_cast<GPR *>(&gpr)), + GPRWordCount); } int RegisterContextMach_arm::DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) { - return ::thread_set_state(tid, flavor, (thread_state_t)&fpu, FPUWordCount); + return ::thread_set_state( + tid, flavor, reinterpret_cast<thread_state_t>(const_cast<FPU *>(&fpu)), + FPUWordCount); } int RegisterContextMach_arm::DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) { - return ::thread_set_state(tid, flavor, (thread_state_t)&exc, EXCWordCount); + return ::thread_set_state( + tid, flavor, reinterpret_cast<thread_state_t>(const_cast<EXC *>(&exc)), + EXCWordCount); } int RegisterContextMach_arm::DoWriteDBG(lldb::tid_t tid, int flavor, const DBG &dbg) { - return ::thread_set_state(tid, flavor, (thread_state_t)&dbg, DBGWordCount); + return ::thread_set_state( + tid, flavor, reinterpret_cast<thread_state_t>(const_cast<DBG *>(&dbg)), + DBGWordCount); } #endif diff --git a/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp b/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp index 959149edbc3e0..5a260d5de1d55 100644 --- a/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp +++ b/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp @@ -43,17 +43,23 @@ int RegisterContextMach_i386::DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) { int RegisterContextMach_i386::DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) { - return ::thread_set_state(tid, flavor, (thread_state_t)&gpr, GPRWordCount); + return ::thread_set_state( + tid, flavor, reinterpret_cast<thread_state_t>(const_cast<GPR *>(&gpr)), + GPRWordCount); } int RegisterContextMach_i386::DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) { - return ::thread_set_state(tid, flavor, (thread_state_t)&fpu, FPUWordCount); + return ::thread_set_state( + tid, flavor, reinterpret_cast<thread_state_t>(const_cast<FPU *>(&fpu)), + FPUWordCount); } int RegisterContextMach_i386::DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) { - return ::thread_set_state(tid, flavor, (thread_state_t)&exc, EXCWordCount); + return ::thread_set_state( + tid, flavor, reinterpret_cast<thread_state_t>(const_cast<EXC *>(&exc)), + EXCWordCount); } #endif diff --git a/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp index 522b73a2888e7..0180879d51eee 100644 --- a/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp @@ -46,17 +46,23 @@ int RegisterContextMach_x86_64::DoReadEXC(lldb::tid_t tid, int flavor, int RegisterContextMach_x86_64::DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) { - return ::thread_set_state(tid, flavor, (thread_state_t)&gpr, GPRWordCount); + return ::thread_set_state( + tid, flavor, reinterpret_cast<thread_state_t>(const_cast<GPR *>(&gpr)), + GPRWordCount); } int RegisterContextMach_x86_64::DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) { - return ::thread_set_state(tid, flavor, (thread_state_t)&fpu, FPUWordCount); + return ::thread_set_state( + tid, flavor, reinterpret_cast<thread_state_t>(const_cast<FPU *>(&fpu)), + FPUWordCount); } int RegisterContextMach_x86_64::DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) { - return ::thread_set_state(tid, flavor, (thread_state_t)&exc, EXCWordCount); + return ::thread_set_state( + tid, flavor, reinterpret_cast<thread_state_t>(const_cast<EXC *>(&exc)), + EXCWordCount); } #endif diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp new file mode 100644 index 0000000000000..de410f063b536 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp @@ -0,0 +1,216 @@ +//===-- RegisterContextPOSIX_ppc64le.cpp -------------------------*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <cstring> +#include <errno.h> +#include <stdint.h> + +#include "lldb/Core/RegisterValue.h" +#include "lldb/Core/Scalar.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" +#include "llvm/Support/Compiler.h" + +#include "Plugins/Process/elf-core/ProcessElfCore.h" +#include "RegisterContextPOSIX_ppc64le.h" + +using namespace lldb_private; +using namespace lldb; + +static const uint32_t g_gpr_regnums[] = { + gpr_r0_ppc64le, gpr_r1_ppc64le, gpr_r2_ppc64le, gpr_r3_ppc64le, + gpr_r4_ppc64le, gpr_r5_ppc64le, gpr_r6_ppc64le, gpr_r7_ppc64le, + gpr_r8_ppc64le, gpr_r9_ppc64le, gpr_r10_ppc64le, gpr_r11_ppc64le, + gpr_r12_ppc64le, gpr_r13_ppc64le, gpr_r14_ppc64le, gpr_r15_ppc64le, + gpr_r16_ppc64le, gpr_r17_ppc64le, gpr_r18_ppc64le, gpr_r19_ppc64le, + gpr_r20_ppc64le, gpr_r21_ppc64le, gpr_r22_ppc64le, gpr_r23_ppc64le, + gpr_r24_ppc64le, gpr_r25_ppc64le, gpr_r26_ppc64le, gpr_r27_ppc64le, + gpr_r28_ppc64le, gpr_r29_ppc64le, gpr_r30_ppc64le, gpr_r31_ppc64le, + gpr_pc_ppc64le, gpr_msr_ppc64le, gpr_origr3_ppc64le, gpr_ctr_ppc64le, + gpr_lr_ppc64le, gpr_xer_ppc64le, gpr_cr_ppc64le, gpr_softe_ppc64le, + gpr_trap_ppc64le, +}; + +static const uint32_t g_fpr_regnums[] = { + fpr_f0_ppc64le, fpr_f1_ppc64le, fpr_f2_ppc64le, fpr_f3_ppc64le, + fpr_f4_ppc64le, fpr_f5_ppc64le, fpr_f6_ppc64le, fpr_f7_ppc64le, + fpr_f8_ppc64le, fpr_f9_ppc64le, fpr_f10_ppc64le, fpr_f11_ppc64le, + fpr_f12_ppc64le, fpr_f13_ppc64le, fpr_f14_ppc64le, fpr_f15_ppc64le, + fpr_f16_ppc64le, fpr_f17_ppc64le, fpr_f18_ppc64le, fpr_f19_ppc64le, + fpr_f20_ppc64le, fpr_f21_ppc64le, fpr_f22_ppc64le, fpr_f23_ppc64le, + fpr_f24_ppc64le, fpr_f25_ppc64le, fpr_f26_ppc64le, fpr_f27_ppc64le, + fpr_f28_ppc64le, fpr_f29_ppc64le, fpr_f30_ppc64le, fpr_f31_ppc64le, + fpr_fpscr_ppc64le, +}; + +static const uint32_t g_vmx_regnums[] = { + vmx_vr0_ppc64le, vmx_vr1_ppc64le, vmx_vr2_ppc64le, vmx_vr3_ppc64le, + vmx_vr4_ppc64le, vmx_vr5_ppc64le, vmx_vr6_ppc64le, vmx_vr7_ppc64le, + vmx_vr8_ppc64le, vmx_vr9_ppc64le, vmx_vr10_ppc64le, vmx_vr11_ppc64le, + vmx_vr12_ppc64le, vmx_vr13_ppc64le, vmx_vr14_ppc64le, vmx_vr15_ppc64le, + vmx_vr16_ppc64le, vmx_vr17_ppc64le, vmx_vr18_ppc64le, vmx_vr19_ppc64le, + vmx_vr20_ppc64le, vmx_vr21_ppc64le, vmx_vr22_ppc64le, vmx_vr23_ppc64le, + vmx_vr24_ppc64le, vmx_vr25_ppc64le, vmx_vr26_ppc64le, vmx_vr27_ppc64le, + vmx_vr28_ppc64le, vmx_vr29_ppc64le, vmx_vr30_ppc64le, vmx_vr31_ppc64le, + vmx_vscr_ppc64le, vmx_vrsave_ppc64le, +}; + +static const uint32_t g_vsx_regnums[] = { + vsx_vs0_ppc64le, vsx_vs1_ppc64le, vsx_vs2_ppc64le, vsx_vs3_ppc64le, + vsx_vs4_ppc64le, vsx_vs5_ppc64le, vsx_vs6_ppc64le, vsx_vs7_ppc64le, + vsx_vs8_ppc64le, vsx_vs9_ppc64le, vsx_vs10_ppc64le, vsx_vs11_ppc64le, + vsx_vs12_ppc64le, vsx_vs13_ppc64le, vsx_vs14_ppc64le, vsx_vs15_ppc64le, + vsx_vs16_ppc64le, vsx_vs17_ppc64le, vsx_vs18_ppc64le, vsx_vs19_ppc64le, + vsx_vs20_ppc64le, vsx_vs21_ppc64le, vsx_vs22_ppc64le, vsx_vs23_ppc64le, + vsx_vs24_ppc64le, vsx_vs25_ppc64le, vsx_vs26_ppc64le, vsx_vs27_ppc64le, + vsx_vs28_ppc64le, vsx_vs29_ppc64le, vsx_vs30_ppc64le, vsx_vs31_ppc64le, + vsx_vs32_ppc64le, vsx_vs33_ppc64le, vsx_vs34_ppc64le, vsx_vs35_ppc64le, + vsx_vs36_ppc64le, vsx_vs37_ppc64le, vsx_vs38_ppc64le, vsx_vs39_ppc64le, + vsx_vs40_ppc64le, vsx_vs41_ppc64le, vsx_vs42_ppc64le, vsx_vs43_ppc64le, + vsx_vs44_ppc64le, vsx_vs45_ppc64le, vsx_vs46_ppc64le, vsx_vs47_ppc64le, + vsx_vs48_ppc64le, vsx_vs49_ppc64le, vsx_vs50_ppc64le, vsx_vs51_ppc64le, + vsx_vs52_ppc64le, vsx_vs53_ppc64le, vsx_vs54_ppc64le, vsx_vs55_ppc64le, + vsx_vs56_ppc64le, vsx_vs57_ppc64le, vsx_vs58_ppc64le, vsx_vs59_ppc64le, + vsx_vs60_ppc64le, vsx_vs61_ppc64le, vsx_vs62_ppc64le, vsx_vs63_ppc64le, +}; + +// Number of register sets provided by this context. +enum { k_num_register_sets = 4 }; + +static const RegisterSet g_reg_sets_ppc64le[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_ppc64le, + g_gpr_regnums}, + {"Floating Point Registers", "fpr", k_num_fpr_registers_ppc64le, + g_fpr_regnums}, + {"Altivec/VMX Registers", "vmx", k_num_vmx_registers_ppc64le, + g_vmx_regnums}, + {"VSX Registers", "vsx", k_num_vsx_registers_ppc64le, g_vsx_regnums}, +}; + +bool RegisterContextPOSIX_ppc64le::IsGPR(unsigned reg) { + return (reg <= k_last_gpr_ppc64le); // GPR's come first. +} + +bool RegisterContextPOSIX_ppc64le::IsFPR(unsigned reg) { + return (reg >= k_first_fpr_ppc64le) && (reg <= k_last_fpr_ppc64le); +} + +bool RegisterContextPOSIX_ppc64le::IsVMX(unsigned reg) { + return (reg >= k_first_vmx_ppc64le) && (reg <= k_last_vmx_ppc64le); +} + +bool RegisterContextPOSIX_ppc64le::IsVSX(unsigned reg) { + return (reg >= k_first_vsx_ppc64le) && (reg <= k_last_vsx_ppc64le); +} + +RegisterContextPOSIX_ppc64le::RegisterContextPOSIX_ppc64le( + Thread &thread, uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info) + : RegisterContext(thread, concrete_frame_idx) { + m_register_info_ap.reset(register_info); + + ProcessSP base = CalculateProcess(); + if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic()) + return; +} + +void RegisterContextPOSIX_ppc64le::InvalidateAllRegisters() {} + +unsigned RegisterContextPOSIX_ppc64le::GetRegisterOffset(unsigned reg) { + assert(reg < k_num_registers_ppc64le && "Invalid register number."); + return GetRegisterInfo()[reg].byte_offset; +} + +unsigned RegisterContextPOSIX_ppc64le::GetRegisterSize(unsigned reg) { + assert(reg < k_num_registers_ppc64le && "Invalid register number."); + return GetRegisterInfo()[reg].byte_size; +} + +size_t RegisterContextPOSIX_ppc64le::GetRegisterCount() { + size_t num_registers = k_num_registers_ppc64le; + return num_registers; +} + +size_t RegisterContextPOSIX_ppc64le::GetGPRSize() { + return m_register_info_ap->GetGPRSize(); +} + +const RegisterInfo *RegisterContextPOSIX_ppc64le::GetRegisterInfo() { + // Commonly, this method is overridden and g_register_infos is copied and + // specialized. + // So, use GetRegisterInfo() rather than g_register_infos in this scope. + return m_register_info_ap->GetRegisterInfo(); +} + +const RegisterInfo * +RegisterContextPOSIX_ppc64le::GetRegisterInfoAtIndex(size_t reg) { + if (reg < k_num_registers_ppc64le) + return &GetRegisterInfo()[reg]; + else + return NULL; +} + +size_t RegisterContextPOSIX_ppc64le::GetRegisterSetCount() { + size_t sets = 0; + for (size_t set = 0; set < k_num_register_sets; ++set) { + if (IsRegisterSetAvailable(set)) + ++sets; + } + + return sets; +} + +const RegisterSet *RegisterContextPOSIX_ppc64le::GetRegisterSet(size_t set) { + if (IsRegisterSetAvailable(set)) + return &g_reg_sets_ppc64le[set]; + else + return NULL; +} + +const char *RegisterContextPOSIX_ppc64le::GetRegisterName(unsigned reg) { + assert(reg < k_num_registers_ppc64le && "Invalid register offset."); + return GetRegisterInfo()[reg].name; +} + +lldb::ByteOrder RegisterContextPOSIX_ppc64le::GetByteOrder() { + // Get the target process whose privileged thread was used for the register + // read. + lldb::ByteOrder byte_order = eByteOrderInvalid; + Process *process = CalculateProcess().get(); + + if (process) + byte_order = process->GetByteOrder(); + return byte_order; +} + +bool RegisterContextPOSIX_ppc64le::IsRegisterSetAvailable(size_t set_index) { + size_t num_sets = k_num_register_sets; + + return (set_index < num_sets); +} + +// Used when parsing DWARF and EH frame information and any other +// object file sections that contain register numbers in them. +uint32_t RegisterContextPOSIX_ppc64le::ConvertRegisterKindToRegisterNumber( + lldb::RegisterKind kind, uint32_t num) { + const uint32_t num_regs = GetRegisterCount(); + + assert(kind < kNumRegisterKinds); + for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx); + + if (reg_info->kinds[kind] == num) + return reg_idx; + } + + return LLDB_INVALID_REGNUM; +} diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.h new file mode 100644 index 0000000000000..1070b4dea4051 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.h @@ -0,0 +1,82 @@ +//===-- RegisterContextPOSIX_ppc64le.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_RegisterContextPOSIX_ppc64le_h_ +#define liblldb_RegisterContextPOSIX_ppc64le_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h" +#include "RegisterInfoInterface.h" +#include "Utility/PPC64LE_DWARF_Registers.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/Log.h" + +class RegisterContextPOSIX_ppc64le : public lldb_private::RegisterContext { +public: + RegisterContextPOSIX_ppc64le( + lldb_private::Thread &thread, uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info); + + void InvalidateAllRegisters() override; + + size_t GetRegisterCount() override; + + virtual size_t GetGPRSize(); + + virtual unsigned GetRegisterSize(unsigned reg); + + virtual unsigned GetRegisterOffset(unsigned reg); + + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; + + size_t GetRegisterSetCount() override; + + const lldb_private::RegisterSet *GetRegisterSet(size_t set) override; + + const char *GetRegisterName(unsigned reg); + + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; + +protected: + // 64-bit general purpose registers. + uint64_t m_gpr_ppc64le[k_num_gpr_registers_ppc64le]; + + // floating-point registers including extended register. + uint64_t m_fpr_ppc64le[k_num_fpr_registers_ppc64le]; + + // VMX registers. + uint64_t m_vmx_ppc64le[k_num_vmx_registers_ppc64le * 2]; + + // VSX registers. + uint64_t m_vsx_ppc64le[k_num_vsx_registers_ppc64le * 2]; + + std::unique_ptr<lldb_private::RegisterInfoInterface> m_register_info_ap; + + // Determines if an extended register set is supported on the processor + // running the inferior process. + virtual bool IsRegisterSetAvailable(size_t set_index); + + virtual const lldb_private::RegisterInfo *GetRegisterInfo(); + + bool IsGPR(unsigned reg); + + bool IsFPR(unsigned reg); + + bool IsVMX(unsigned reg); + + bool IsVSX(unsigned reg); + + lldb::ByteOrder GetByteOrder(); +}; + +#endif // liblldb_RegisterContextPOSIX_ppc64le_h_ diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp index 5e1bf35356b8f..41cec8add9875 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp @@ -365,12 +365,6 @@ RegisterContextPOSIX_x86::RegisterContextPOSIX_x86( break; } - // Initialize m_iovec to point to the buffer and buffer size - // using the conventions of Berkeley style UIO structures, as required - // by PTRACE extensions. - m_iovec.iov_base = &m_fpr.xstate.xsave; - m_iovec.iov_len = sizeof(m_fpr.xstate.xsave); - ::memset(&m_fpr, 0, sizeof(FPR)); m_fpr_type = eNotValid; @@ -481,19 +475,19 @@ bool RegisterContextPOSIX_x86::CopyYMMtoXSTATE(uint32_t reg, return false; if (byte_order == eByteOrderLittle) { - ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + ::memcpy(m_fpr.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(XMMReg)); - ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + ::memcpy(m_fpr.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), sizeof(YMMHReg)); return true; } if (byte_order == eByteOrderBig) { - ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + ::memcpy(m_fpr.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), sizeof(XMMReg)); - ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + ::memcpy(m_fpr.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(YMMHReg)); return true; } @@ -508,20 +502,20 @@ bool RegisterContextPOSIX_x86::CopyXSTATEtoYMM(uint32_t reg, if (byte_order == eByteOrderLittle) { ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, - m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + m_fpr.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, sizeof(XMMReg)); ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), - m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + m_fpr.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, sizeof(YMMHReg)); return true; } if (byte_order == eByteOrderBig) { ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), - m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + m_fpr.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, sizeof(XMMReg)); ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, - m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + m_fpr.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, sizeof(YMMHReg)); return true; } diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h index aa689273f2189..ca71a6f272f80 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h @@ -149,9 +149,9 @@ protected: RegInfo m_reg_info; FPRType m_fpr_type; // determines the type of data stored by union FPR, if any. - FPR m_fpr; // floating-point registers including extended register sets. - IOVEC m_iovec; // wrapper for xsave. - YMM m_ymm_set; // copy of ymmh and xmm register halves. + lldb_private::FPR m_fpr; // floating-point registers including extended + // register sets. + lldb_private::YMM m_ymm_set; // copy of ymmh and xmm register halves. std::unique_ptr<lldb_private::RegisterInfoInterface> m_register_info_ap; // Register Info Interface (FreeBSD or Linux) diff --git a/source/Plugins/Process/Utility/RegisterContext_mips.h b/source/Plugins/Process/Utility/RegisterContext_mips.h index 565747cb4bd71..da470bd827327 100644 --- a/source/Plugins/Process/Utility/RegisterContext_mips.h +++ b/source/Plugins/Process/Utility/RegisterContext_mips.h @@ -241,11 +241,6 @@ enum { dwarf_config5_mips64, }; -struct IOVEC_mips { - void *iov_base; - size_t iov_len; -}; - // GP registers struct GPR_linux_mips { uint64_t zero; diff --git a/source/Plugins/Process/Utility/RegisterContext_x86.h b/source/Plugins/Process/Utility/RegisterContext_x86.h index 5f6fc295a15c1..6146dcaf7e5a2 100644 --- a/source/Plugins/Process/Utility/RegisterContext_x86.h +++ b/source/Plugins/Process/Utility/RegisterContext_x86.h @@ -13,8 +13,10 @@ #include <cstddef> #include <cstdint> +#include "llvm/ADT/BitmaskEnum.h" #include "llvm/Support/Compiler.h" +namespace lldb_private { //--------------------------------------------------------------------------- // i386 ehframe, dwarf regnums //--------------------------------------------------------------------------- @@ -313,13 +315,28 @@ struct MPX { LLVM_PACKED_START struct XSAVE_HDR { - uint64_t xstate_bv; // OS enabled xstate mask to determine the extended states + enum class XFeature : uint64_t { + FP = 1, + SSE = FP << 1, + YMM = SSE << 1, + BNDREGS = YMM << 1, + BNDCSR = BNDREGS << 1, + OPMASK = BNDCSR << 1, + ZMM_Hi256 = OPMASK << 1, + Hi16_ZMM = ZMM_Hi256 << 1, + PT = Hi16_ZMM << 1, + PKRU = PT << 1, + LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue*/ PKRU) + }; + + XFeature xstate_bv; // OS enabled xstate mask to determine the extended states // supported by the processor - uint64_t xcomp_bv; // Mask to indicate the format of the XSAVE area and of + XFeature xcomp_bv; // Mask to indicate the format of the XSAVE area and of // the XRSTOR instruction uint64_t reserved1[1]; uint64_t reserved2[5]; }; +static_assert(sizeof(XSAVE_HDR) == 64, "XSAVE_HDR layout incorrect"); LLVM_PACKED_END // x86 extensions to FXSAVE (i.e. for AVX and MPX processors) @@ -338,21 +355,13 @@ struct LLVM_ALIGNAS(64) XSAVE { LLVM_PACKED_END // Floating-point registers -struct FPR { - // Thread state for the floating-point unit of the processor read by ptrace. - union XSTATE { - FXSAVE fxsave; // Generic floating-point registers. - XSAVE xsave; // x86 extended processor state. - } xstate; +union FPR { + FXSAVE fxsave; // Generic floating-point registers. + XSAVE xsave; // x86 extended processor state. }; -//--------------------------------------------------------------------------- -// ptrace PTRACE_GETREGSET, PTRACE_SETREGSET structure -//--------------------------------------------------------------------------- +LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); -struct IOVEC { - void *iov_base; // pointer to XSAVE - size_t iov_len; // sizeof(XSAVE) -}; +} // namespace lldb_private #endif diff --git a/source/Plugins/Process/Utility/RegisterInfoInterface.h b/source/Plugins/Process/Utility/RegisterInfoInterface.h index 74d5d6e502085..1894b53681224 100644 --- a/source/Plugins/Process/Utility/RegisterInfoInterface.h +++ b/source/Plugins/Process/Utility/RegisterInfoInterface.h @@ -10,10 +10,9 @@ #ifndef lldb_RegisterInfoInterface_h #define lldb_RegisterInfoInterface_h -#include <vector> - -#include "lldb/Core/ArchSpec.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/lldb-private-types.h" +#include <vector> namespace lldb_private { diff --git a/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp b/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp new file mode 100644 index 0000000000000..e5e7350fe68ad --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp @@ -0,0 +1,66 @@ +//===-- RegisterInfoPOSIX_ppc64le.cpp --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// + +#include <cassert> +#include <stddef.h> +#include <vector> + +#include "lldb/lldb-defines.h" +#include "llvm/Support/Compiler.h" + +#include "RegisterInfoPOSIX_ppc64le.h" + +//----------------------------------------------------------------------------- +// Include RegisterInfoPOSIX_ppc64le to declare our g_register_infos_ppc64le +//----------------------------------------------------------------------------- +#define DECLARE_REGISTER_INFOS_PPC64LE_STRUCT +#include "RegisterInfos_ppc64le.h" +#undef DECLARE_REGISTER_INFOS_PPC64LE_STRUCT + +static const lldb_private::RegisterInfo * +GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::ppc64le: + return g_register_infos_ppc64le; + default: + assert(false && "Unhandled target architecture."); + return NULL; + } +} + +static uint32_t +GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::ppc64le: + return static_cast<uint32_t>(sizeof(g_register_infos_ppc64le) / + sizeof(g_register_infos_ppc64le[0])); + default: + assert(false && "Unhandled target architecture."); + return 0; + } +} + +RegisterInfoPOSIX_ppc64le::RegisterInfoPOSIX_ppc64le( + const lldb_private::ArchSpec &target_arch) + : lldb_private::RegisterInfoInterface(target_arch), + m_register_info_p(GetRegisterInfoPtr(target_arch)), + m_register_info_count(GetRegisterInfoCount(target_arch)) {} + +size_t RegisterInfoPOSIX_ppc64le::GetGPRSize() const { + return sizeof(GPR); +} + +const lldb_private::RegisterInfo * +RegisterInfoPOSIX_ppc64le::GetRegisterInfo() const { + return m_register_info_p; +} + +uint32_t RegisterInfoPOSIX_ppc64le::GetRegisterCount() const { + return m_register_info_count; +} diff --git a/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h b/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h new file mode 100644 index 0000000000000..411ab05c2b13d --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h @@ -0,0 +1,32 @@ +//===-- RegisterInfoPOSIX_ppc64le.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_RegisterContextLinux_ppc64le_H_ +#define liblldb_RegisterContextLinux_ppc64le_H_ + +#include "RegisterInfoInterface.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/lldb-private.h" + +class RegisterInfoPOSIX_ppc64le : public lldb_private::RegisterInfoInterface { +public: + RegisterInfoPOSIX_ppc64le(const lldb_private::ArchSpec &target_arch); + + size_t GetGPRSize() const override; + + const lldb_private::RegisterInfo *GetRegisterInfo() const override; + + uint32_t GetRegisterCount() const override; + +private: + const lldb_private::RegisterInfo *m_register_info_p; + uint32_t m_register_info_count; +}; + +#endif diff --git a/source/Plugins/Process/Utility/RegisterInfos_i386.h b/source/Plugins/Process/Utility/RegisterInfos_i386.h index 8597d0c39dc48..ffdc4d0d116b0 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_i386.h +++ b/source/Plugins/Process/Utility/RegisterInfos_i386.h @@ -27,19 +27,19 @@ // Based on DNBArchImplI386.cpp from debugserver #define YMM_OFFSET(reg_index) \ (LLVM_EXTENSION offsetof(UserArea, i387) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ + LLVM_EXTENSION offsetof(FPR, fxsave) + \ LLVM_EXTENSION offsetof(FXSAVE, xmm[7]) + sizeof(XMMReg) + \ (32 * reg_index)) -#define BNDR_OFFSET(reg_index) \ - (LLVM_EXTENSION offsetof(UserArea, i387) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ - LLVM_EXTENSION offsetof(XSAVE, mpxr[reg_index])) +#define BNDR_OFFSET(reg_index) \ + (LLVM_EXTENSION offsetof(UserArea, i387) + \ + LLVM_EXTENSION offsetof(FPR, xsave) + \ + LLVM_EXTENSION offsetof(XSAVE, mpxr[reg_index])) -#define BNDC_OFFSET(reg_index) \ - (LLVM_EXTENSION offsetof(UserArea, i387) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ - LLVM_EXTENSION offsetof(XSAVE, mpxc[reg_index])) +#define BNDC_OFFSET(reg_index) \ + (LLVM_EXTENSION offsetof(UserArea, i387) + \ + LLVM_EXTENSION offsetof(FPR, xsave) + \ + LLVM_EXTENSION offsetof(XSAVE, mpxc[reg_index])) // Number of bytes needed to represent a FPR. #if !defined(FPR_SIZE) diff --git a/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h b/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h new file mode 100644 index 0000000000000..bffa7a1d8b635 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h @@ -0,0 +1,476 @@ +//===-- RegisterInfos_ppc64le.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifdef DECLARE_REGISTER_INFOS_PPC64LE_STRUCT + +// C Includes +#include <stddef.h> + +// Computes the offset of the given GPR in the user data area. +#define GPR_OFFSET(regname) (offsetof(GPR, regname)) +#define FPR_OFFSET(regname) (offsetof(FPR, regname) + sizeof(GPR)) +#define VMX_OFFSET(regname) (offsetof(VMX, regname) + sizeof(GPR) + sizeof(FPR)) +#define VSX_OFFSET(regname) \ + (offsetof(VSX, regname) + sizeof(GPR) + sizeof(FPR) + sizeof(VMX)) +#define GPR_SIZE(regname) (sizeof(((GPR *)NULL)->regname)) + +#include "Utility/PPC64LE_DWARF_Registers.h" +#include "lldb-ppc64le-register-enums.h" + +// Note that the size and offset will be updated by platform-specific classes. +#define DEFINE_GPR(reg, alt, lldb_kind) \ + { \ + #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), lldb::eEncodingUint, \ + lldb::eFormatHex, \ + {ppc64le_dwarf::dwarf_##reg##_ppc64le,\ + ppc64le_dwarf::dwarf_##reg##_ppc64le,\ + lldb_kind, \ + LLDB_INVALID_REGNUM, \ + gpr_##reg##_ppc64le }, \ + NULL, NULL, NULL, 0 \ + } +#define DEFINE_FPR(reg, alt, lldb_kind) \ + { \ +#reg, alt, 8, FPR_OFFSET(reg), lldb::eEncodingIEEE754, lldb::eFormatFloat, \ + {ppc64le_dwarf::dwarf_##reg##_ppc64le, \ + ppc64le_dwarf::dwarf_##reg##_ppc64le, lldb_kind, LLDB_INVALID_REGNUM, \ + fpr_##reg##_ppc64le }, \ + NULL, NULL, NULL, 0 \ + } +#define DEFINE_VMX(reg, lldb_kind) \ + { \ +#reg, NULL, 16, VMX_OFFSET(reg), lldb::eEncodingVector, \ + lldb::eFormatVectorOfUInt32, \ + {ppc64le_dwarf::dwarf_##reg##_ppc64le, \ + ppc64le_dwarf::dwarf_##reg##_ppc64le, lldb_kind, LLDB_INVALID_REGNUM, \ + vmx_##reg##_ppc64le }, \ + NULL, NULL, NULL, 0 \ + } +#define DEFINE_VSX(reg, lldb_kind) \ + { \ +#reg, NULL, 16, VSX_OFFSET(reg), lldb::eEncodingVector, \ + lldb::eFormatVectorOfUInt32, \ + {ppc64le_dwarf::dwarf_##reg##_ppc64le, \ + ppc64le_dwarf::dwarf_##reg##_ppc64le, lldb_kind, LLDB_INVALID_REGNUM, \ + vsx_##reg##_ppc64le }, \ + NULL, NULL, NULL, 0 \ + } + +// General purpose registers. +// EH_Frame, Generic, Process Plugin +#define POWERPC_REGS \ + DEFINE_GPR(r0, NULL, LLDB_INVALID_REGNUM) \ + , DEFINE_GPR(r1, "sp", LLDB_REGNUM_GENERIC_SP), \ + DEFINE_GPR(r2, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r3, "arg1", LLDB_REGNUM_GENERIC_ARG1), \ + DEFINE_GPR(r4, "arg2", LLDB_REGNUM_GENERIC_ARG2), \ + DEFINE_GPR(r5, "arg3", LLDB_REGNUM_GENERIC_ARG3), \ + DEFINE_GPR(r6, "arg4", LLDB_REGNUM_GENERIC_ARG4), \ + DEFINE_GPR(r7, "arg5", LLDB_REGNUM_GENERIC_ARG5), \ + DEFINE_GPR(r8, "arg6", LLDB_REGNUM_GENERIC_ARG6), \ + DEFINE_GPR(r9, "arg7", LLDB_REGNUM_GENERIC_ARG7), \ + DEFINE_GPR(r10, "arg8", LLDB_REGNUM_GENERIC_ARG8), \ + DEFINE_GPR(r11, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r12, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r13, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r14, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r15, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r16, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r17, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r18, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r19, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r20, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r21, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r22, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r23, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r24, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r25, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r26, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r27, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r28, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r29, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r30, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r31, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(pc, "pc", LLDB_REGNUM_GENERIC_PC), \ + DEFINE_GPR(msr, "msr", LLDB_INVALID_REGNUM), \ + DEFINE_GPR(origr3, "orig_r3", LLDB_INVALID_REGNUM), \ + DEFINE_GPR(ctr, "ctr", LLDB_INVALID_REGNUM), \ + DEFINE_GPR(lr, "lr", LLDB_REGNUM_GENERIC_RA), \ + DEFINE_GPR(xer, "xer", LLDB_INVALID_REGNUM), \ + DEFINE_GPR(cr, "cr", LLDB_REGNUM_GENERIC_FLAGS), \ + DEFINE_GPR(softe, "softe", LLDB_INVALID_REGNUM), \ + DEFINE_GPR(trap, "trap", LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f0, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f1, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f2, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f3, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f4, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f5, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f6, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f7, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f8, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f9, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f10, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f11, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f12, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f13, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f14, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f15, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f16, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f17, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f18, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f19, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f20, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f21, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f22, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f23, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f24, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f25, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f26, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f27, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f28, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f29, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f30, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f31, NULL, LLDB_INVALID_REGNUM), \ + {"fpscr", \ + NULL, \ + 8, \ + FPR_OFFSET(fpscr), \ + lldb::eEncodingUint, \ + lldb::eFormatHex, \ + {ppc64le_dwarf::dwarf_fpscr_ppc64le, \ + ppc64le_dwarf::dwarf_fpscr_ppc64le, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, fpr_fpscr_ppc64le}, \ + NULL, \ + NULL, \ + NULL, \ + 0}, \ + DEFINE_VMX(vr0, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr1, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr2, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr3, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr4, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr5, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr6, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr7, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr8, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr9, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr10, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr11, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr12, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr13, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr14, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr15, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr16, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr17, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr18, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr19, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr20, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr21, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr22, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr23, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr24, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr25, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr26, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr27, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr28, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr29, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr30, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr31, LLDB_INVALID_REGNUM), \ + {"vscr", \ + NULL, \ + 4, \ + VMX_OFFSET(vscr), \ + lldb::eEncodingUint, \ + lldb::eFormatHex, \ + {ppc64le_dwarf::dwarf_vscr_ppc64le, ppc64le_dwarf::dwarf_vscr_ppc64le, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, vmx_vscr_ppc64le}, \ + NULL, \ + NULL, \ + NULL, \ + 0}, \ + {"vrsave", \ + NULL, \ + 4, \ + VMX_OFFSET(vrsave), \ + lldb::eEncodingUint, \ + lldb::eFormatHex, \ + {ppc64le_dwarf::dwarf_vrsave_ppc64le, \ + ppc64le_dwarf::dwarf_vrsave_ppc64le, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, vmx_vrsave_ppc64le}, \ + NULL, \ + NULL, \ + NULL, \ + 0}, \ + DEFINE_VSX(vs0, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs1, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs2, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs3, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs4, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs5, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs6, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs7, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs8, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs9, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs10, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs11, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs12, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs13, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs14, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs15, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs16, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs17, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs18, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs19, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs20, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs21, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs22, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs23, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs24, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs25, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs26, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs27, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs28, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs29, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs30, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs31, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs32, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs33, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs34, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs35, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs36, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs37, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs38, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs39, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs40, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs41, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs42, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs43, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs44, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs45, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs46, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs47, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs48, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs49, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs50, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs51, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs52, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs53, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs54, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs55, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs56, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs57, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs58, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs59, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs50, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs61, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs62, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs63, LLDB_INVALID_REGNUM), /* */ + +typedef struct _GPR { + uint64_t r0; + uint64_t r1; + uint64_t r2; + uint64_t r3; + uint64_t r4; + uint64_t r5; + uint64_t r6; + uint64_t r7; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t r16; + uint64_t r17; + uint64_t r18; + uint64_t r19; + uint64_t r20; + uint64_t r21; + uint64_t r22; + uint64_t r23; + uint64_t r24; + uint64_t r25; + uint64_t r26; + uint64_t r27; + uint64_t r28; + uint64_t r29; + uint64_t r30; + uint64_t r31; + uint64_t pc; + uint64_t msr; + uint64_t origr3; + uint64_t ctr; + uint64_t lr; + uint64_t xer; + uint64_t cr; + uint64_t softe; + uint64_t trap; + uint64_t pad[3]; +} GPR; + +typedef struct _FPR { + uint64_t f0; + uint64_t f1; + uint64_t f2; + uint64_t f3; + uint64_t f4; + uint64_t f5; + uint64_t f6; + uint64_t f7; + uint64_t f8; + uint64_t f9; + uint64_t f10; + uint64_t f11; + uint64_t f12; + uint64_t f13; + uint64_t f14; + uint64_t f15; + uint64_t f16; + uint64_t f17; + uint64_t f18; + uint64_t f19; + uint64_t f20; + uint64_t f21; + uint64_t f22; + uint64_t f23; + uint64_t f24; + uint64_t f25; + uint64_t f26; + uint64_t f27; + uint64_t f28; + uint64_t f29; + uint64_t f30; + uint64_t f31; + uint64_t fpscr; +} FPR; + +typedef struct _VMX { + uint32_t vr0[4]; + uint32_t vr1[4]; + uint32_t vr2[4]; + uint32_t vr3[4]; + uint32_t vr4[4]; + uint32_t vr5[4]; + uint32_t vr6[4]; + uint32_t vr7[4]; + uint32_t vr8[4]; + uint32_t vr9[4]; + uint32_t vr10[4]; + uint32_t vr11[4]; + uint32_t vr12[4]; + uint32_t vr13[4]; + uint32_t vr14[4]; + uint32_t vr15[4]; + uint32_t vr16[4]; + uint32_t vr17[4]; + uint32_t vr18[4]; + uint32_t vr19[4]; + uint32_t vr20[4]; + uint32_t vr21[4]; + uint32_t vr22[4]; + uint32_t vr23[4]; + uint32_t vr24[4]; + uint32_t vr25[4]; + uint32_t vr26[4]; + uint32_t vr27[4]; + uint32_t vr28[4]; + uint32_t vr29[4]; + uint32_t vr30[4]; + uint32_t vr31[4]; + uint32_t pad[2]; + uint32_t vscr[2]; + uint32_t vrsave; +} VMX; + +typedef struct _VSX { + uint32_t vs0[4]; + uint32_t vs1[4]; + uint32_t vs2[4]; + uint32_t vs3[4]; + uint32_t vs4[4]; + uint32_t vs5[4]; + uint32_t vs6[4]; + uint32_t vs7[4]; + uint32_t vs8[4]; + uint32_t vs9[4]; + uint32_t vs10[4]; + uint32_t vs11[4]; + uint32_t vs12[4]; + uint32_t vs13[4]; + uint32_t vs14[4]; + uint32_t vs15[4]; + uint32_t vs16[4]; + uint32_t vs17[4]; + uint32_t vs18[4]; + uint32_t vs19[4]; + uint32_t vs20[4]; + uint32_t vs21[4]; + uint32_t vs22[4]; + uint32_t vs23[4]; + uint32_t vs24[4]; + uint32_t vs25[4]; + uint32_t vs26[4]; + uint32_t vs27[4]; + uint32_t vs28[4]; + uint32_t vs29[4]; + uint32_t vs30[4]; + uint32_t vs31[4]; + uint32_t vs32[4]; + uint32_t vs33[4]; + uint32_t vs34[4]; + uint32_t vs35[4]; + uint32_t vs36[4]; + uint32_t vs37[4]; + uint32_t vs38[4]; + uint32_t vs39[4]; + uint32_t vs40[4]; + uint32_t vs41[4]; + uint32_t vs42[4]; + uint32_t vs43[4]; + uint32_t vs44[4]; + uint32_t vs45[4]; + uint32_t vs46[4]; + uint32_t vs47[4]; + uint32_t vs48[4]; + uint32_t vs49[4]; + uint32_t vs50[4]; + uint32_t vs51[4]; + uint32_t vs52[4]; + uint32_t vs53[4]; + uint32_t vs54[4]; + uint32_t vs55[4]; + uint32_t vs56[4]; + uint32_t vs57[4]; + uint32_t vs58[4]; + uint32_t vs59[4]; + uint32_t vs60[4]; + uint32_t vs61[4]; + uint32_t vs62[4]; + uint32_t vs63[4]; +} VSX; + +static lldb_private::RegisterInfo g_register_infos_ppc64le[] = { + POWERPC_REGS +}; + +static_assert((sizeof(g_register_infos_ppc64le) / + sizeof(g_register_infos_ppc64le[0])) == + k_num_registers_ppc64le, + "g_register_infos_powerpc64 has wrong number of register infos"); + +#undef DEFINE_FPR +#undef DEFINE_GPR +#undef DEFINE_VMX +#undef DEFINE_VSX + +#endif // DECLARE_REGISTER_INFOS_PPC64LE_STRUCT diff --git a/source/Plugins/Process/Utility/RegisterInfos_x86_64.h b/source/Plugins/Process/Utility/RegisterInfos_x86_64.h index 8861ecd668062..651536cb60450 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_x86_64.h +++ b/source/Plugins/Process/Utility/RegisterInfos_x86_64.h @@ -7,11 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/Compiler.h" -#include <cstddef> -#include <cstdint> - -// Project includes +// This file is meant to be textually included. Do not #include modular +// headers here. // Computes the offset of the given GPR in the user data area. #define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR, regname)) @@ -19,25 +16,25 @@ // Computes the offset of the given FPR in the extended data area. #define FPR_OFFSET(regname) \ (LLVM_EXTENSION offsetof(UserArea, fpr) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ + LLVM_EXTENSION offsetof(FPR, fxsave) + \ LLVM_EXTENSION offsetof(FXSAVE, regname)) // Computes the offset of the YMM register assembled from register halves. // Based on DNBArchImplX86_64.cpp from debugserver #define YMM_OFFSET(reg_index) \ (LLVM_EXTENSION offsetof(UserArea, fpr) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ + LLVM_EXTENSION offsetof(FPR, xsave) + \ LLVM_EXTENSION offsetof(XSAVE, ymmh[0]) + (32 * reg_index)) -#define BNDR_OFFSET(reg_index) \ - (LLVM_EXTENSION offsetof(UserArea, fpr) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ - LLVM_EXTENSION offsetof(XSAVE, mpxr[reg_index])) +#define BNDR_OFFSET(reg_index) \ + (LLVM_EXTENSION offsetof(UserArea, fpr) + \ + LLVM_EXTENSION offsetof(FPR, xsave) + \ + LLVM_EXTENSION offsetof(XSAVE, mpxr[reg_index])) -#define BNDC_OFFSET(reg_index) \ - (LLVM_EXTENSION offsetof(UserArea, fpr) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ - LLVM_EXTENSION offsetof(XSAVE, mpxc[reg_index])) +#define BNDC_OFFSET(reg_index) \ + (LLVM_EXTENSION offsetof(UserArea, fpr) + \ + LLVM_EXTENSION offsetof(FPR, xsave) + \ + LLVM_EXTENSION offsetof(XSAVE, mpxc[reg_index])) #ifdef DECLARE_REGISTER_INFOS_X86_64_STRUCT diff --git a/source/Plugins/Process/Utility/StopInfoMachException.cpp b/source/Plugins/Process/Utility/StopInfoMachException.cpp index 435f3d18c0625..3e860874183cf 100644 --- a/source/Plugins/Process/Utility/StopInfoMachException.cpp +++ b/source/Plugins/Process/Utility/StopInfoMachException.cpp @@ -14,7 +14,6 @@ // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/Watchpoint.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/ExecutionContext.h" diff --git a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp index f907735d8f587..d831011cb6612 100644 --- a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp +++ b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp @@ -7,11 +7,6 @@ // //===----------------------------------------------------------------------===// -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Symbol.h" @@ -19,6 +14,7 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/ArchSpec.h" #include "RegisterContextMacOSXFrameBackchain.h" @@ -85,8 +81,6 @@ size_t UnwindMacOSXFrameBackchain::GetStackFrameData_i386( if (process == NULL) return 0; - std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair; - struct Frame_i386 { uint32_t fp; uint32_t pc; @@ -179,8 +173,6 @@ size_t UnwindMacOSXFrameBackchain::GetStackFrameData_x86_64( StackFrame *first_frame = exe_ctx.GetFramePtr(); - std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair; - struct Frame_x86_64 { uint64_t fp; uint64_t pc; diff --git a/source/Plugins/Process/Utility/lldb-ppc64le-register-enums.h b/source/Plugins/Process/Utility/lldb-ppc64le-register-enums.h new file mode 100644 index 0000000000000..675804d132680 --- /dev/null +++ b/source/Plugins/Process/Utility/lldb-ppc64le-register-enums.h @@ -0,0 +1,210 @@ +//===-- lldb-ppc64le-register-enums.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_ppc64le_register_enums_h +#define lldb_ppc64le_register_enums_h + +// LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) + +// --------------------------------------------------------------------------- +// Internal codes for all ppc64le registers. +// --------------------------------------------------------------------------- +enum { + k_first_gpr_ppc64le, + gpr_r0_ppc64le = k_first_gpr_ppc64le, + gpr_r1_ppc64le, + gpr_r2_ppc64le, + gpr_r3_ppc64le, + gpr_r4_ppc64le, + gpr_r5_ppc64le, + gpr_r6_ppc64le, + gpr_r7_ppc64le, + gpr_r8_ppc64le, + gpr_r9_ppc64le, + gpr_r10_ppc64le, + gpr_r11_ppc64le, + gpr_r12_ppc64le, + gpr_r13_ppc64le, + gpr_r14_ppc64le, + gpr_r15_ppc64le, + gpr_r16_ppc64le, + gpr_r17_ppc64le, + gpr_r18_ppc64le, + gpr_r19_ppc64le, + gpr_r20_ppc64le, + gpr_r21_ppc64le, + gpr_r22_ppc64le, + gpr_r23_ppc64le, + gpr_r24_ppc64le, + gpr_r25_ppc64le, + gpr_r26_ppc64le, + gpr_r27_ppc64le, + gpr_r28_ppc64le, + gpr_r29_ppc64le, + gpr_r30_ppc64le, + gpr_r31_ppc64le, + gpr_pc_ppc64le, + gpr_msr_ppc64le, + gpr_origr3_ppc64le, + gpr_ctr_ppc64le, + gpr_lr_ppc64le, + gpr_xer_ppc64le, + gpr_cr_ppc64le, + gpr_softe_ppc64le, + gpr_trap_ppc64le, + k_last_gpr_ppc64le = gpr_trap_ppc64le, + + k_first_fpr_ppc64le, + fpr_f0_ppc64le = k_first_fpr_ppc64le, + fpr_f1_ppc64le, + fpr_f2_ppc64le, + fpr_f3_ppc64le, + fpr_f4_ppc64le, + fpr_f5_ppc64le, + fpr_f6_ppc64le, + fpr_f7_ppc64le, + fpr_f8_ppc64le, + fpr_f9_ppc64le, + fpr_f10_ppc64le, + fpr_f11_ppc64le, + fpr_f12_ppc64le, + fpr_f13_ppc64le, + fpr_f14_ppc64le, + fpr_f15_ppc64le, + fpr_f16_ppc64le, + fpr_f17_ppc64le, + fpr_f18_ppc64le, + fpr_f19_ppc64le, + fpr_f20_ppc64le, + fpr_f21_ppc64le, + fpr_f22_ppc64le, + fpr_f23_ppc64le, + fpr_f24_ppc64le, + fpr_f25_ppc64le, + fpr_f26_ppc64le, + fpr_f27_ppc64le, + fpr_f28_ppc64le, + fpr_f29_ppc64le, + fpr_f30_ppc64le, + fpr_f31_ppc64le, + fpr_fpscr_ppc64le, + k_last_fpr_ppc64le = fpr_fpscr_ppc64le, + + k_first_vmx_ppc64le, + vmx_vr0_ppc64le = k_first_vmx_ppc64le, + vmx_vr1_ppc64le, + vmx_vr2_ppc64le, + vmx_vr3_ppc64le, + vmx_vr4_ppc64le, + vmx_vr5_ppc64le, + vmx_vr6_ppc64le, + vmx_vr7_ppc64le, + vmx_vr8_ppc64le, + vmx_vr9_ppc64le, + vmx_vr10_ppc64le, + vmx_vr11_ppc64le, + vmx_vr12_ppc64le, + vmx_vr13_ppc64le, + vmx_vr14_ppc64le, + vmx_vr15_ppc64le, + vmx_vr16_ppc64le, + vmx_vr17_ppc64le, + vmx_vr18_ppc64le, + vmx_vr19_ppc64le, + vmx_vr20_ppc64le, + vmx_vr21_ppc64le, + vmx_vr22_ppc64le, + vmx_vr23_ppc64le, + vmx_vr24_ppc64le, + vmx_vr25_ppc64le, + vmx_vr26_ppc64le, + vmx_vr27_ppc64le, + vmx_vr28_ppc64le, + vmx_vr29_ppc64le, + vmx_vr30_ppc64le, + vmx_vr31_ppc64le, + vmx_vscr_ppc64le, + vmx_vrsave_ppc64le, + k_last_vmx_ppc64le = vmx_vrsave_ppc64le, + + k_first_vsx_ppc64le, + vsx_vs0_ppc64le = k_first_vsx_ppc64le, + vsx_vs1_ppc64le, + vsx_vs2_ppc64le, + vsx_vs3_ppc64le, + vsx_vs4_ppc64le, + vsx_vs5_ppc64le, + vsx_vs6_ppc64le, + vsx_vs7_ppc64le, + vsx_vs8_ppc64le, + vsx_vs9_ppc64le, + vsx_vs10_ppc64le, + vsx_vs11_ppc64le, + vsx_vs12_ppc64le, + vsx_vs13_ppc64le, + vsx_vs14_ppc64le, + vsx_vs15_ppc64le, + vsx_vs16_ppc64le, + vsx_vs17_ppc64le, + vsx_vs18_ppc64le, + vsx_vs19_ppc64le, + vsx_vs20_ppc64le, + vsx_vs21_ppc64le, + vsx_vs22_ppc64le, + vsx_vs23_ppc64le, + vsx_vs24_ppc64le, + vsx_vs25_ppc64le, + vsx_vs26_ppc64le, + vsx_vs27_ppc64le, + vsx_vs28_ppc64le, + vsx_vs29_ppc64le, + vsx_vs30_ppc64le, + vsx_vs31_ppc64le, + vsx_vs32_ppc64le, + vsx_vs33_ppc64le, + vsx_vs34_ppc64le, + vsx_vs35_ppc64le, + vsx_vs36_ppc64le, + vsx_vs37_ppc64le, + vsx_vs38_ppc64le, + vsx_vs39_ppc64le, + vsx_vs40_ppc64le, + vsx_vs41_ppc64le, + vsx_vs42_ppc64le, + vsx_vs43_ppc64le, + vsx_vs44_ppc64le, + vsx_vs45_ppc64le, + vsx_vs46_ppc64le, + vsx_vs47_ppc64le, + vsx_vs48_ppc64le, + vsx_vs49_ppc64le, + vsx_vs50_ppc64le, + vsx_vs51_ppc64le, + vsx_vs52_ppc64le, + vsx_vs53_ppc64le, + vsx_vs54_ppc64le, + vsx_vs55_ppc64le, + vsx_vs56_ppc64le, + vsx_vs57_ppc64le, + vsx_vs58_ppc64le, + vsx_vs59_ppc64le, + vsx_vs60_ppc64le, + vsx_vs61_ppc64le, + vsx_vs62_ppc64le, + vsx_vs63_ppc64le, + k_last_vsx_ppc64le = vsx_vs63_ppc64le, + + k_num_registers_ppc64le, + k_num_gpr_registers_ppc64le = k_last_gpr_ppc64le - k_first_gpr_ppc64le + 1, + k_num_fpr_registers_ppc64le = k_last_fpr_ppc64le - k_first_fpr_ppc64le + 1, + k_num_vmx_registers_ppc64le = k_last_vmx_ppc64le - k_first_vmx_ppc64le + 1, + k_num_vsx_registers_ppc64le = k_last_vsx_ppc64le - k_first_vsx_ppc64le + 1, +}; + +#endif // #ifndef lldb_ppc64le_register_enums_h diff --git a/source/Plugins/Process/elf-core/CMakeLists.txt b/source/Plugins/Process/elf-core/CMakeLists.txt index c7ffae6953207..3082c73f6dda7 100644 --- a/source/Plugins/Process/elf-core/CMakeLists.txt +++ b/source/Plugins/Process/elf-core/CMakeLists.txt @@ -7,8 +7,10 @@ add_lldb_library(lldbPluginProcessElfCore PLUGIN RegisterContextPOSIXCore_arm64.cpp RegisterContextPOSIXCore_mips64.cpp RegisterContextPOSIXCore_powerpc.cpp + RegisterContextPOSIXCore_ppc64le.cpp RegisterContextPOSIXCore_s390x.cpp RegisterContextPOSIXCore_x86_64.cpp + RegisterUtilities.cpp LINK_LIBS lldbCore diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp index 71eb6437ceed1..7d6a0c9ad2df0 100644 --- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -32,8 +32,7 @@ #include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" #include "Plugins/ObjectFile/ELF/ObjectFileELF.h" - -// Project includes +#include "Plugins/Process/elf-core/RegisterUtilities.h" #include "ProcessElfCore.h" #include "ThreadElfCore.h" @@ -101,10 +100,7 @@ bool ProcessElfCore::CanDebug(lldb::TargetSP target_sp, ProcessElfCore::ProcessElfCore(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec &core_file) - : Process(target_sp, listener_sp), m_core_module_sp(), - m_core_file(core_file), m_dyld_plugin_name(), - m_os(llvm::Triple::UnknownOS), m_thread_data_valid(false), - m_thread_data(), m_core_aranges() {} + : Process(target_sp, listener_sp), m_core_file(core_file) {} //---------------------------------------------------------------------- // Destructor @@ -193,9 +189,8 @@ Status ProcessElfCore::DoLoadCore() { // Parse thread contexts and auxv structure if (header->p_type == llvm::ELF::PT_NOTE) { - error = ParseThreadContextsFromNoteSegment(header, data); - if (error.Fail()) - return error; + if (llvm::Error error = ParseThreadContextsFromNoteSegment(header, data)) + return Status(std::move(error)); } // PT_LOAD segments contains address map if (header->p_type == llvm::ELF::PT_LOAD) { @@ -404,7 +399,6 @@ size_t ProcessElfCore::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, void ProcessElfCore::Clear() { m_thread_list.Clear(); - m_os = llvm::Triple::UnknownOS; SetUnixSignals(std::make_shared<UnixSignals>()); } @@ -427,43 +421,10 @@ lldb::addr_t ProcessElfCore::GetImageInfoAddress() { return LLDB_INVALID_ADDRESS; } -/// Core files PT_NOTE segment descriptor types -enum { - NT_PRSTATUS = 1, - NT_FPREGSET, - NT_PRPSINFO, - NT_TASKSTRUCT, - NT_PLATFORM, - NT_AUXV, - NT_FILE = 0x46494c45, - NT_PRXFPREG = 0x46e62b7f, - NT_SIGINFO = 0x53494749, - NT_OPENBSD_PROCINFO = 10, - NT_OPENBSD_AUXV = 11, - NT_OPENBSD_REGS = 20, - NT_OPENBSD_FPREGS = 21, -}; - -namespace FREEBSD { - -enum { - NT_PRSTATUS = 1, - NT_FPREGSET, - NT_PRPSINFO, - NT_THRMISC = 7, - NT_PROCSTAT_AUXV = 16, - NT_PPC_VMX = 0x100 -}; -} - -namespace NETBSD { - -enum { NT_PROCINFO = 1, NT_AUXV, NT_AMD64_REGS = 33, NT_AMD64_FPREGS = 35 }; -} - // Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details. -static void ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data, - ArchSpec &arch) { +static void ParseFreeBSDPrStatus(ThreadData &thread_data, + const DataExtractor &data, + const ArchSpec &arch) { lldb::offset_t offset = 0; bool lp64 = (arch.GetMachine() == llvm::Triple::aarch64 || arch.GetMachine() == llvm::Triple::mips64 || @@ -492,12 +453,8 @@ static void ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data, thread_data.gpregset = DataExtractor(data, offset, len); } -static void ParseFreeBSDThrMisc(ThreadData &thread_data, DataExtractor &data) { - lldb::offset_t offset = 0; - thread_data.name = data.GetCStr(&offset, 20); -} - -static void ParseNetBSDProcInfo(ThreadData &thread_data, DataExtractor &data) { +static void ParseNetBSDProcInfo(ThreadData &thread_data, + const DataExtractor &data) { lldb::offset_t offset = 0; int version = data.GetU32(&offset); @@ -508,7 +465,8 @@ static void ParseNetBSDProcInfo(ThreadData &thread_data, DataExtractor &data) { thread_data.signo = data.GetU32(&offset); } -static void ParseOpenBSDProcInfo(ThreadData &thread_data, DataExtractor &data) { +static void ParseOpenBSDProcInfo(ThreadData &thread_data, + const DataExtractor &data) { lldb::offset_t offset = 0; int version = data.GetU32(&offset); @@ -519,202 +477,263 @@ static void ParseOpenBSDProcInfo(ThreadData &thread_data, DataExtractor &data) { thread_data.signo = data.GetU32(&offset); } -/// Parse Thread context from PT_NOTE segment and store it in the thread list -/// Notes: -/// 1) A PT_NOTE segment is composed of one or more NOTE entries. -/// 2) NOTE Entry contains a standard header followed by variable size data. -/// (see ELFNote structure) -/// 3) A Thread Context in a core file usually described by 3 NOTE entries. -/// a) NT_PRSTATUS - Register context -/// b) NT_PRPSINFO - Process info(pid..) -/// c) NT_FPREGSET - Floating point registers -/// 4) The NOTE entries can be in any order -/// 5) If a core file contains multiple thread contexts then there is two data -/// forms -/// a) Each thread context(2 or more NOTE entries) contained in its own -/// segment (PT_NOTE) -/// b) All thread context is stored in a single segment(PT_NOTE). -/// This case is little tricker since while parsing we have to find where -/// the -/// new thread starts. The current implementation marks beginning of -/// new thread when it finds NT_PRSTATUS or NT_PRPSINFO NOTE entry. -/// For case (b) there may be either one NT_PRPSINFO per thread, or a single -/// one that applies to all threads (depending on the platform type). -Status ProcessElfCore::ParseThreadContextsFromNoteSegment( - const elf::ELFProgramHeader *segment_header, DataExtractor segment_data) { - assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE); - +llvm::Expected<std::vector<CoreNote>> +ProcessElfCore::parseSegment(const DataExtractor &segment) { lldb::offset_t offset = 0; - std::unique_ptr<ThreadData> thread_data(new ThreadData); + std::vector<CoreNote> result; + + while (offset < segment.GetByteSize()) { + ELFNote note = ELFNote(); + if (!note.Parse(segment, &offset)) + return llvm::make_error<llvm::StringError>( + "Unable to parse note segment", llvm::inconvertibleErrorCode()); + + size_t note_start = offset; + size_t note_size = llvm::alignTo(note.n_descsz, 4); + DataExtractor note_data(segment, note_start, note_size); + + result.push_back({note, note_data}); + offset += note_size; + } + + return std::move(result); +} + +llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) { bool have_prstatus = false; bool have_prpsinfo = false; + ThreadData thread_data; + for (const auto ¬e : notes) { + if (note.info.n_name != "FreeBSD") + continue; + + if ((note.info.n_type == FREEBSD::NT_PRSTATUS && have_prstatus) || + (note.info.n_type == FREEBSD::NT_PRPSINFO && have_prpsinfo)) { + assert(thread_data.gpregset.GetByteSize() > 0); + // Add the new thread to thread list + m_thread_data.push_back(thread_data); + thread_data = ThreadData(); + have_prstatus = false; + have_prpsinfo = false; + } - ArchSpec arch = GetArchitecture(); - ELFLinuxPrPsInfo prpsinfo; - ELFLinuxPrStatus prstatus; - ELFLinuxSigInfo siginfo; - size_t header_size; - size_t len; - Status error; + switch (note.info.n_type) { + case FREEBSD::NT_PRSTATUS: + have_prstatus = true; + ParseFreeBSDPrStatus(thread_data, note.data, GetArchitecture()); + break; + case FREEBSD::NT_PRPSINFO: + have_prpsinfo = true; + break; + case FREEBSD::NT_THRMISC: { + lldb::offset_t offset = 0; + thread_data.name = note.data.GetCStr(&offset, 20); + break; + } + case FREEBSD::NT_PROCSTAT_AUXV: + // FIXME: FreeBSD sticks an int at the beginning of the note + m_auxv = DataExtractor(note.data, 4, note.data.GetByteSize() - 4); + break; + default: + thread_data.notes.push_back(note); + break; + } + } + if (!have_prstatus) { + return llvm::make_error<llvm::StringError>( + "Could not find NT_PRSTATUS note in core file.", + llvm::inconvertibleErrorCode()); + } + m_thread_data.push_back(thread_data); + return llvm::Error::success(); +} - // Loop through the NOTE entires in the segment - while (offset < segment_header->p_filesz) { - ELFNote note = ELFNote(); - note.Parse(segment_data, &offset); +llvm::Error ProcessElfCore::parseNetBSDNotes(llvm::ArrayRef<CoreNote> notes) { + ThreadData thread_data; + for (const auto ¬e : notes) { + // NetBSD per-thread information is stored in notes named + // "NetBSD-CORE@nnn" so match on the initial part of the string. + if (!llvm::StringRef(note.info.n_name).startswith("NetBSD-CORE")) + continue; + + switch (note.info.n_type) { + case NETBSD::NT_PROCINFO: + ParseNetBSDProcInfo(thread_data, note.data); + break; + case NETBSD::NT_AUXV: + m_auxv = note.data; + break; + + case NETBSD::NT_AMD64_REGS: + if (GetArchitecture().GetMachine() == llvm::Triple::x86_64) + thread_data.gpregset = note.data; + break; + default: + thread_data.notes.push_back(note); + break; + } + } + if (thread_data.gpregset.GetByteSize() == 0) { + return llvm::make_error<llvm::StringError>( + "Could not find general purpose registers note in core file.", + llvm::inconvertibleErrorCode()); + } + m_thread_data.push_back(thread_data); + return llvm::Error::success(); +} + +llvm::Error ProcessElfCore::parseOpenBSDNotes(llvm::ArrayRef<CoreNote> notes) { + ThreadData thread_data; + for (const auto ¬e : notes) { + // OpenBSD per-thread information is stored in notes named + // "OpenBSD@nnn" so match on the initial part of the string. + if (!llvm::StringRef(note.info.n_name).startswith("OpenBSD")) + continue; + + switch (note.info.n_type) { + case OPENBSD::NT_PROCINFO: + ParseOpenBSDProcInfo(thread_data, note.data); + break; + case OPENBSD::NT_AUXV: + m_auxv = note.data; + break; + case OPENBSD::NT_REGS: + thread_data.gpregset = note.data; + break; + default: + thread_data.notes.push_back(note); + break; + } + } + if (thread_data.gpregset.GetByteSize() == 0) { + return llvm::make_error<llvm::StringError>( + "Could not find general purpose registers note in core file.", + llvm::inconvertibleErrorCode()); + } + m_thread_data.push_back(thread_data); + return llvm::Error::success(); +} - // Beginning of new thread - if ((note.n_type == NT_PRSTATUS && have_prstatus) || - (note.n_type == NT_PRPSINFO && have_prpsinfo)) { - assert(thread_data->gpregset.GetByteSize() > 0); +/// A description of a linux process usually contains the following NOTE +/// entries: +/// - NT_PRPSINFO - General process information like pid, uid, name, ... +/// - NT_SIGINFO - Information about the signal that terminated the process +/// - NT_AUXV - Process auxiliary vector +/// - NT_FILE - Files mapped into memory +/// +/// Additionally, for each thread in the process the core file will contain at +/// least the NT_PRSTATUS note, containing the thread id and general purpose +/// registers. It may include additional notes for other register sets (floating +/// point and vector registers, ...). The tricky part here is that some of these +/// notes have "CORE" in their owner fields, while other set it to "LINUX". +llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) { + const ArchSpec &arch = GetArchitecture(); + bool have_prstatus = false; + bool have_prpsinfo = false; + ThreadData thread_data; + for (const auto ¬e : notes) { + if (note.info.n_name != "CORE" && note.info.n_name != "LINUX") + continue; + + if ((note.info.n_type == LINUX::NT_PRSTATUS && have_prstatus) || + (note.info.n_type == LINUX::NT_PRPSINFO && have_prpsinfo)) { + assert(thread_data.gpregset.GetByteSize() > 0); // Add the new thread to thread list - m_thread_data.push_back(*thread_data); - *thread_data = ThreadData(); + m_thread_data.push_back(thread_data); + thread_data = ThreadData(); have_prstatus = false; have_prpsinfo = false; } - size_t note_start, note_size; - note_start = offset; - note_size = llvm::alignTo(note.n_descsz, 4); - - // Store the NOTE information in the current thread - DataExtractor note_data(segment_data, note_start, note_size); - note_data.SetAddressByteSize( - m_core_module_sp->GetArchitecture().GetAddressByteSize()); - if (note.n_name == "FreeBSD") { - m_os = llvm::Triple::FreeBSD; - switch (note.n_type) { - case FREEBSD::NT_PRSTATUS: - have_prstatus = true; - ParseFreeBSDPrStatus(*thread_data, note_data, arch); - break; - case FREEBSD::NT_FPREGSET: - thread_data->fpregset = note_data; - break; - case FREEBSD::NT_PRPSINFO: - have_prpsinfo = true; - break; - case FREEBSD::NT_THRMISC: - ParseFreeBSDThrMisc(*thread_data, note_data); - break; - case FREEBSD::NT_PROCSTAT_AUXV: - // 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; - } - } else if (note.n_name.substr(0, 11) == "NetBSD-CORE") { - // NetBSD per-thread information is stored in notes named - // "NetBSD-CORE@nnn" so match on the initial part of the string. - m_os = llvm::Triple::NetBSD; - if (note.n_type == NETBSD::NT_PROCINFO) { - ParseNetBSDProcInfo(*thread_data, note_data); - } else if (note.n_type == NETBSD::NT_AUXV) { - m_auxv = DataExtractor(note_data); - } else if (arch.GetMachine() == llvm::Triple::x86_64 && - note.n_type == NETBSD::NT_AMD64_REGS) { - thread_data->gpregset = note_data; - } else if (arch.GetMachine() == llvm::Triple::x86_64 && - note.n_type == NETBSD::NT_AMD64_FPREGS) { - thread_data->fpregset = note_data; - } - } else if (note.n_name.substr(0, 7) == "OpenBSD") { - // OpenBSD per-thread information is stored in notes named - // "OpenBSD@nnn" so match on the initial part of the string. - m_os = llvm::Triple::OpenBSD; - switch (note.n_type) { - case NT_OPENBSD_PROCINFO: - ParseOpenBSDProcInfo(*thread_data, note_data); - break; - case NT_OPENBSD_AUXV: - m_auxv = DataExtractor(note_data); - break; - case NT_OPENBSD_REGS: - thread_data->gpregset = note_data; - break; - case NT_OPENBSD_FPREGS: - thread_data->fpregset = note_data; - break; - } - } else if (note.n_name == "CORE") { - switch (note.n_type) { - case NT_PRSTATUS: - have_prstatus = true; - error = prstatus.Parse(note_data, arch); - if (error.Fail()) - return error; - thread_data->prstatus_sig = prstatus.pr_cursig; - thread_data->tid = prstatus.pr_pid; - header_size = ELFLinuxPrStatus::GetSize(arch); - len = note_data.GetByteSize() - header_size; - thread_data->gpregset = DataExtractor(note_data, header_size, len); - break; - case NT_FPREGSET: - // In a i386 core file NT_FPREGSET is present, but it's not the result - // of the FXSAVE instruction like in 64 bit files. - // The result from FXSAVE is in NT_PRXFPREG for i386 core files - if (arch.GetCore() == ArchSpec::eCore_x86_64_x86_64) - thread_data->fpregset = note_data; - else if(arch.IsMIPS()) - thread_data->fpregset = note_data; - break; - case NT_PRPSINFO: - have_prpsinfo = true; - error = prpsinfo.Parse(note_data, arch); - if (error.Fail()) - return error; - thread_data->name = prpsinfo.pr_fname; - SetID(prpsinfo.pr_pid); - break; - case NT_AUXV: - m_auxv = DataExtractor(note_data); - break; - case NT_FILE: { - m_nt_file_entries.clear(); - lldb::offset_t offset = 0; - const uint64_t count = note_data.GetAddress(&offset); - note_data.GetAddress(&offset); // Skip page size - for (uint64_t i = 0; i < count; ++i) { - NT_FILE_Entry entry; - entry.start = note_data.GetAddress(&offset); - entry.end = note_data.GetAddress(&offset); - entry.file_ofs = note_data.GetAddress(&offset); - m_nt_file_entries.push_back(entry); - } - for (uint64_t i = 0; i < count; ++i) { - const char *path = note_data.GetCStr(&offset); - if (path && path[0]) - m_nt_file_entries[i].path.SetCString(path); - } - } break; - case NT_SIGINFO: { - error = siginfo.Parse(note_data, arch); - if (error.Fail()) - return error; - thread_data->signo = siginfo.si_signo; - } break; - default: - break; + switch (note.info.n_type) { + case LINUX::NT_PRSTATUS: { + have_prstatus = true; + ELFLinuxPrStatus prstatus; + Status status = prstatus.Parse(note.data, arch); + if (status.Fail()) + return status.ToError(); + thread_data.prstatus_sig = prstatus.pr_cursig; + thread_data.tid = prstatus.pr_pid; + uint32_t header_size = ELFLinuxPrStatus::GetSize(arch); + size_t len = note.data.GetByteSize() - header_size; + thread_data.gpregset = DataExtractor(note.data, header_size, len); + break; + } + case LINUX::NT_PRPSINFO: { + have_prpsinfo = true; + ELFLinuxPrPsInfo prpsinfo; + Status status = prpsinfo.Parse(note.data, arch); + if (status.Fail()) + return status.ToError(); + thread_data.name = prpsinfo.pr_fname; + SetID(prpsinfo.pr_pid); + break; + } + case LINUX::NT_SIGINFO: { + ELFLinuxSigInfo siginfo; + Status status = siginfo.Parse(note.data, arch); + if (status.Fail()) + return status.ToError(); + thread_data.signo = siginfo.si_signo; + break; + } + case LINUX::NT_FILE: { + m_nt_file_entries.clear(); + lldb::offset_t offset = 0; + const uint64_t count = note.data.GetAddress(&offset); + note.data.GetAddress(&offset); // Skip page size + for (uint64_t i = 0; i < count; ++i) { + NT_FILE_Entry entry; + entry.start = note.data.GetAddress(&offset); + entry.end = note.data.GetAddress(&offset); + entry.file_ofs = note.data.GetAddress(&offset); + m_nt_file_entries.push_back(entry); } - } else if (note.n_name == "LINUX") { - switch (note.n_type) { - case NT_PRXFPREG: - thread_data->fpregset = note_data; + for (uint64_t i = 0; i < count; ++i) { + const char *path = note.data.GetCStr(&offset); + if (path && path[0]) + m_nt_file_entries[i].path.SetCString(path); } + break; + } + case LINUX::NT_AUXV: + m_auxv = note.data; + break; + default: + thread_data.notes.push_back(note); + break; } - - offset += note_size; } // Add last entry in the note section - if (thread_data && thread_data->gpregset.GetByteSize() > 0) { - m_thread_data.push_back(*thread_data); - } + if (have_prstatus) + m_thread_data.push_back(thread_data); + return llvm::Error::success(); +} - return error; +/// Parse Thread context from PT_NOTE segment and store it in the thread list +/// A note segment consists of one or more NOTE entries, but their types and +/// meaning differ depending on the OS. +llvm::Error ProcessElfCore::ParseThreadContextsFromNoteSegment( + const elf::ELFProgramHeader *segment_header, DataExtractor segment_data) { + assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE); + + auto notes_or_error = parseSegment(segment_data); + if(!notes_or_error) + return notes_or_error.takeError(); + switch (GetArchitecture().GetTriple().getOS()) { + case llvm::Triple::FreeBSD: + return parseFreeBSDNotes(*notes_or_error); + case llvm::Triple::Linux: + return parseLinuxNotes(*notes_or_error); + case llvm::Triple::NetBSD: + return parseNetBSDNotes(*notes_or_error); + case llvm::Triple::OpenBSD: + return parseOpenBSDNotes(*notes_or_error); + default: + return llvm::make_error<llvm::StringError>( + "Don't know how to parse core file. Unsupported OS.", + llvm::inconvertibleErrorCode()); + } } uint32_t ProcessElfCore::GetNumThreadContexts() { @@ -724,15 +743,18 @@ uint32_t ProcessElfCore::GetNumThreadContexts() { } ArchSpec ProcessElfCore::GetArchitecture() { - ObjectFileELF *core_file = - (ObjectFileELF *)(m_core_module_sp->GetObjectFile()); ArchSpec arch; - core_file->GetArchitecture(arch); + m_core_module_sp->GetObjectFile()->GetArchitecture(arch); ArchSpec target_arch = GetTarget().GetArchitecture(); - - if (target_arch.IsMIPS()) + arch.MergeFrom(target_arch); + + // On MIPS there is no way to differentiate betwenn 32bit and 64bit core files + // and this information can't be merged in from the target arch so we fail + // back to unconditionally returning the target arch in this config. + if (target_arch.IsMIPS()) { return target_arch; + } return arch; } diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.h b/source/Plugins/Process/elf-core/ProcessElfCore.h index dbf7f926f8551..325c0152e0287 100644 --- a/source/Plugins/Process/elf-core/ProcessElfCore.h +++ b/source/Plugins/Process/elf-core/ProcessElfCore.h @@ -29,6 +29,7 @@ #include "lldb/Utility/Status.h" #include "Plugins/ObjectFile/ELF/ELFHeader.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" struct ThreadData; @@ -84,11 +85,21 @@ public: void RefreshStateAfterStop() override; + lldb_private::Status WillResume() override { + lldb_private::Status error; + error.SetErrorStringWithFormat( + "error: %s does not support resuming processes", + GetPluginName().GetCString()); + return error; + } + //------------------------------------------------------------------ // Process Queries //------------------------------------------------------------------ bool IsAlive() override; + bool WarnBeforeDetach() const override { return false; } + //------------------------------------------------------------------ // Process Memory //------------------------------------------------------------------ @@ -139,10 +150,8 @@ private: std::string m_dyld_plugin_name; DISALLOW_COPY_AND_ASSIGN(ProcessElfCore); - llvm::Triple::OSType m_os; - // True if m_thread_contexts contains valid entries - bool m_thread_data_valid; + bool m_thread_data_valid = false; // Contain thread data read from NOTE segments std::vector<ThreadData> m_thread_data; @@ -160,7 +169,7 @@ private: std::vector<NT_FILE_Entry> m_nt_file_entries; // Parse thread(s) data structures(prstatus, prpsinfo) from given NOTE segment - lldb_private::Status ParseThreadContextsFromNoteSegment( + llvm::Error ParseThreadContextsFromNoteSegment( const elf::ELFProgramHeader *segment_header, lldb_private::DataExtractor segment_data); @@ -170,6 +179,13 @@ private: // Parse a contiguous address range of the process from LOAD segment lldb::addr_t AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *header); + + llvm::Expected<std::vector<lldb_private::CoreNote>> + parseSegment(const lldb_private::DataExtractor &segment); + llvm::Error parseFreeBSDNotes(llvm::ArrayRef<lldb_private::CoreNote> notes); + llvm::Error parseNetBSDNotes(llvm::ArrayRef<lldb_private::CoreNote> notes); + llvm::Error parseOpenBSDNotes(llvm::ArrayRef<lldb_private::CoreNote> notes); + llvm::Error parseLinuxNotes(llvm::ArrayRef<lldb_private::CoreNote> notes); }; #endif // liblldb_ProcessElfCore_h_ diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp index 81d88e69b97ff..0d683153d9ed0 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp @@ -16,7 +16,7 @@ using namespace lldb_private; RegisterContextCorePOSIX_arm::RegisterContextCorePOSIX_arm( Thread &thread, RegisterInfoInterface *register_info, - const DataExtractor &gpregset, const DataExtractor &fpregset) + const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes) : RegisterContextPOSIX_arm(thread, 0, register_info) { m_gpr_buffer.reset( new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h index e095eac5eaf81..a98d64caee17a 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h @@ -10,11 +10,8 @@ #ifndef liblldb_RegisterContextCorePOSIX_arm_h_ #define liblldb_RegisterContextCorePOSIX_arm_h_ -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes #include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataExtractor.h" @@ -24,7 +21,7 @@ public: lldb_private::Thread &thread, lldb_private::RegisterInfoInterface *register_info, const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset); + llvm::ArrayRef<lldb_private::CoreNote> notes); ~RegisterContextCorePOSIX_arm() override; diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp index 41c02bf94c377..919f8901d39a3 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// #include "RegisterContextPOSIXCore_arm64.h" - +#include "Plugins/Process/elf-core/RegisterUtilities.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Target/Thread.h" @@ -16,7 +16,7 @@ using namespace lldb_private; RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64( Thread &thread, RegisterInfoInterface *register_info, - const DataExtractor &gpregset, const DataExtractor &fpregset) + const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes) : RegisterContextPOSIX_arm64(thread, 0, register_info) { m_gpr_buffer.reset( new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h index 3a2bbdb0a2ebf..c519b15571893 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h @@ -10,11 +10,8 @@ #ifndef liblldb_RegisterContextCorePOSIX_arm64_h_ #define liblldb_RegisterContextCorePOSIX_arm64_h_ -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes #include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataExtractor.h" @@ -24,7 +21,7 @@ public: lldb_private::Thread &thread, lldb_private::RegisterInfoInterface *register_info, const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset); + llvm::ArrayRef<lldb_private::CoreNote> notes); ~RegisterContextCorePOSIX_arm64() override; diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp index 7549cf074be7f..e252b5a35e9c8 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp @@ -16,12 +16,15 @@ using namespace lldb_private; RegisterContextCorePOSIX_mips64::RegisterContextCorePOSIX_mips64( Thread &thread, RegisterInfoInterface *register_info, - const DataExtractor &gpregset, const DataExtractor &fpregset) + const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes) : RegisterContextPOSIX_mips64(thread, 0, register_info) { m_gpr_buffer.reset( new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); m_gpr.SetData(m_gpr_buffer); m_gpr.SetByteOrder(gpregset.GetByteOrder()); + + DataExtractor fpregset = getRegset( + notes, register_info->GetTargetArchitecture().GetTriple(), FPR_Desc); m_fpr_buffer.reset( new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize())); m_fpr.SetData(m_fpr_buffer); diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h index 2cb527a8de7c5..cf1d8a5bc2d11 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h @@ -10,11 +10,8 @@ #ifndef liblldb_RegisterContextCorePOSIX_mips64_h_ #define liblldb_RegisterContextCorePOSIX_mips64_h_ -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes #include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataExtractor.h" @@ -24,7 +21,7 @@ public: lldb_private::Thread &thread, lldb_private::RegisterInfoInterface *register_info, const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset); + llvm::ArrayRef<lldb_private::CoreNote> notes); ~RegisterContextCorePOSIX_mips64() override; diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp index 62f6413722f73..8670e341a2777 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp @@ -17,17 +17,21 @@ using namespace lldb_private; RegisterContextCorePOSIX_powerpc::RegisterContextCorePOSIX_powerpc( Thread &thread, RegisterInfoInterface *register_info, - const DataExtractor &gpregset, const DataExtractor &fpregset, - const DataExtractor &vregset) + const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes) : RegisterContextPOSIX_powerpc(thread, 0, register_info) { m_gpr_buffer.reset( new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); m_gpr.SetData(m_gpr_buffer); m_gpr.SetByteOrder(gpregset.GetByteOrder()); + + ArchSpec arch = register_info->GetTargetArchitecture(); + DataExtractor fpregset = getRegset(notes, arch.GetTriple(), FPR_Desc); m_fpr_buffer.reset( new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize())); m_fpr.SetData(m_fpr_buffer); m_fpr.SetByteOrder(fpregset.GetByteOrder()); + + DataExtractor vregset = getRegset(notes, arch.GetTriple(), PPC_VMX_Desc); m_vec_buffer.reset( new DataBufferHeap(vregset.GetDataStart(), vregset.GetByteSize())); m_vec.SetData(m_vec_buffer); diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h index aaa95e5d2397f..c352ab5912ff0 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h @@ -10,11 +10,8 @@ #ifndef liblldb_RegisterContextCorePOSIX_powerpc_h_ #define liblldb_RegisterContextCorePOSIX_powerpc_h_ -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes #include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" #include "lldb/Utility/DataExtractor.h" class RegisterContextCorePOSIX_powerpc : public RegisterContextPOSIX_powerpc { @@ -23,8 +20,7 @@ public: lldb_private::Thread &thread, lldb_private::RegisterInfoInterface *register_info, const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset, - const lldb_private::DataExtractor &vregset); + llvm::ArrayRef<lldb_private::CoreNote> notes); ~RegisterContextCorePOSIX_powerpc() override; diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.cpp new file mode 100644 index 0000000000000..2237e72353acf --- /dev/null +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.cpp @@ -0,0 +1,132 @@ +//===-- RegisterContextPOSIXCore_ppc64le.cpp --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "RegisterContextPOSIXCore_ppc64le.h" + +#include "lldb/Core/RegisterValue.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" + +#include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" + +using namespace lldb_private; + +RegisterContextCorePOSIX_ppc64le::RegisterContextCorePOSIX_ppc64le( + Thread &thread, RegisterInfoInterface *register_info, + const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes) + : RegisterContextPOSIX_ppc64le(thread, 0, register_info) { + m_gpr_buffer.reset( + new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); + m_gpr.SetData(m_gpr_buffer); + m_gpr.SetByteOrder(gpregset.GetByteOrder()); + + ArchSpec arch = register_info->GetTargetArchitecture(); + DataExtractor fpregset = getRegset(notes, arch.GetTriple(), FPR_Desc); + m_fpr_buffer.reset( + new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize())); + m_fpr.SetData(m_fpr_buffer); + m_fpr.SetByteOrder(fpregset.GetByteOrder()); + + DataExtractor vmxregset = getRegset(notes, arch.GetTriple(), PPC_VMX_Desc); + m_vmx_buffer.reset( + new DataBufferHeap(vmxregset.GetDataStart(), vmxregset.GetByteSize())); + m_vmx.SetData(m_vmx_buffer); + m_vmx.SetByteOrder(vmxregset.GetByteOrder()); + + DataExtractor vsxregset = getRegset(notes, arch.GetTriple(), PPC_VSX_Desc); + m_vsx_buffer.reset( + new DataBufferHeap(vsxregset.GetDataStart(), vsxregset.GetByteSize())); + m_vsx.SetData(m_vsx_buffer); + m_vsx.SetByteOrder(vsxregset.GetByteOrder()); +} + +size_t RegisterContextCorePOSIX_ppc64le::GetFPRSize() const { + return k_num_fpr_registers_ppc64le * sizeof(uint64_t); +} + +size_t RegisterContextCorePOSIX_ppc64le::GetVMXSize() const { + return (k_num_vmx_registers_ppc64le - 1) * sizeof(uint64_t) * 2 + + sizeof(uint32_t); +} + +size_t RegisterContextCorePOSIX_ppc64le::GetVSXSize() const { + return k_num_vsx_registers_ppc64le * sizeof(uint64_t) * 2; +} + +bool RegisterContextCorePOSIX_ppc64le::ReadRegister( + const RegisterInfo *reg_info, RegisterValue &value) { + lldb::offset_t offset = reg_info->byte_offset; + + if (IsFPR(reg_info->kinds[lldb::eRegisterKindLLDB])) { + uint64_t v; + offset -= GetGPRSize(); + offset = m_fpr.CopyData(offset, reg_info->byte_size, &v); + + if (offset == reg_info->byte_size) { + value.SetBytes(&v, reg_info->byte_size, m_fpr.GetByteOrder()); + return true; + } + } else if (IsVMX(reg_info->kinds[lldb::eRegisterKindLLDB])) { + uint32_t v[4]; + offset -= GetGPRSize() + GetFPRSize(); + offset = m_vmx.CopyData(offset, reg_info->byte_size, &v); + + if (offset == reg_info->byte_size) { + value.SetBytes(v, reg_info->byte_size, m_vmx.GetByteOrder()); + return true; + } + } else if (IsVSX(reg_info->kinds[lldb::eRegisterKindLLDB])) { + uint32_t v[4]; + lldb::offset_t tmp_offset; + offset -= GetGPRSize() + GetFPRSize() + GetVMXSize(); + + if (offset < GetVSXSize() / 2) { + tmp_offset = m_vsx.CopyData(offset / 2, reg_info->byte_size / 2, &v); + + if (tmp_offset != reg_info->byte_size / 2) { + return false; + } + + uint8_t *dst = (uint8_t *)&v + sizeof(uint64_t); + tmp_offset = m_fpr.CopyData(offset / 2, reg_info->byte_size / 2, dst); + + if (tmp_offset != reg_info->byte_size / 2) { + return false; + } + + value.SetBytes(&v, reg_info->byte_size, m_vsx.GetByteOrder()); + return true; + } else { + offset = + m_vmx.CopyData(offset - GetVSXSize() / 2, reg_info->byte_size, &v); + if (offset == reg_info->byte_size) { + value.SetBytes(v, reg_info->byte_size, m_vmx.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) { + if (reg_info->byte_size < sizeof(v)) + value = (uint32_t)v; + else + value = v; + return true; + } + } + + return false; +} + +bool RegisterContextCorePOSIX_ppc64le::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue &value) { + return false; +} diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.h new file mode 100644 index 0000000000000..c860781d60be9 --- /dev/null +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.h @@ -0,0 +1,49 @@ +//===-- RegisterContextPOSIXCore_ppc64le.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_RegisterContextCorePOSIX_ppc64le_h_ +#define liblldb_RegisterContextCorePOSIX_ppc64le_h_ + +#include "Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" +#include "lldb/Utility/DataExtractor.h" + +class RegisterContextCorePOSIX_ppc64le : public RegisterContextPOSIX_ppc64le { +public: + RegisterContextCorePOSIX_ppc64le( + lldb_private::Thread &thread, + lldb_private::RegisterInfoInterface *register_info, + const lldb_private::DataExtractor &gpregset, + llvm::ArrayRef<lldb_private::CoreNote> notes); + + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) override; + + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) override; + +protected: + size_t GetFPRSize() const; + + size_t GetVMXSize() const; + + size_t GetVSXSize() const; + +private: + lldb::DataBufferSP m_gpr_buffer; + lldb::DataBufferSP m_fpr_buffer; + lldb::DataBufferSP m_vmx_buffer; + lldb::DataBufferSP m_vsx_buffer; + lldb_private::DataExtractor m_gpr; + lldb_private::DataExtractor m_fpr; + lldb_private::DataExtractor m_vmx; + lldb_private::DataExtractor m_vsx; +}; + +#endif // liblldb_RegisterContextCorePOSIX_ppc64le_h_ diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp index b3530a8d6a42f..f0edbf1ea8548 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp @@ -17,13 +17,15 @@ using namespace lldb_private; RegisterContextCorePOSIX_s390x::RegisterContextCorePOSIX_s390x( Thread &thread, RegisterInfoInterface *register_info, - const DataExtractor &gpregset, const DataExtractor &fpregset) + const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes) : RegisterContextPOSIX_s390x(thread, 0, register_info) { m_gpr_buffer.reset( new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); m_gpr.SetData(m_gpr_buffer); m_gpr.SetByteOrder(gpregset.GetByteOrder()); + DataExtractor fpregset = getRegset( + notes, register_info->GetTargetArchitecture().GetTriple(), FPR_Desc); m_fpr_buffer.reset( new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize())); m_fpr.SetData(m_fpr_buffer); diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h index 2b4ae10a87bd9..0df136372bdda 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h @@ -10,11 +10,8 @@ #ifndef liblldb_RegisterContextCorePOSIX_s390x_h_ #define liblldb_RegisterContextCorePOSIX_s390x_h_ -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes #include "Plugins/Process/Utility/RegisterContextPOSIX_s390x.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" #include "lldb/Utility/DataExtractor.h" class RegisterContextCorePOSIX_s390x : public RegisterContextPOSIX_s390x { @@ -23,7 +20,7 @@ public: lldb_private::Thread &thread, lldb_private::RegisterInfoInterface *register_info, const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset); + llvm::ArrayRef<lldb_private::CoreNote> notes); ~RegisterContextCorePOSIX_s390x() override; diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp index 5766923186d19..a5c7ffda1da56 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp @@ -16,7 +16,7 @@ using namespace lldb_private; RegisterContextCorePOSIX_x86_64::RegisterContextCorePOSIX_x86_64( Thread &thread, RegisterInfoInterface *register_info, - const DataExtractor &gpregset, const DataExtractor &fpregset) + const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes) : RegisterContextPOSIX_x86(thread, 0, register_info) { size_t size, len; @@ -27,6 +27,8 @@ RegisterContextCorePOSIX_x86_64::RegisterContextCorePOSIX_x86_64( if (len != size) m_gpregset.reset(); + DataExtractor fpregset = getRegset( + notes, register_info->GetTargetArchitecture().GetTriple(), FPR_Desc); size = sizeof(FXSAVE); m_fpregset.reset(new uint8_t[size]); len = diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h index 8340368f8c3c9..509624174a89e 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h @@ -10,11 +10,8 @@ #ifndef liblldb_RegisterContextCorePOSIX_x86_64_h_ #define liblldb_RegisterContextCorePOSIX_x86_64_h_ -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes #include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" class RegisterContextCorePOSIX_x86_64 : public RegisterContextPOSIX_x86 { public: @@ -22,7 +19,7 @@ public: lldb_private::Thread &thread, lldb_private::RegisterInfoInterface *register_info, const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset); + llvm::ArrayRef<lldb_private::CoreNote> notes); bool ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value) override; diff --git a/source/Plugins/Process/elf-core/RegisterUtilities.cpp b/source/Plugins/Process/elf-core/RegisterUtilities.cpp new file mode 100644 index 0000000000000..3837abadd0f6c --- /dev/null +++ b/source/Plugins/Process/elf-core/RegisterUtilities.cpp @@ -0,0 +1,39 @@ +//===-- RegisterUtilities.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Plugins/Process/elf-core/RegisterUtilities.h" +#include "llvm/ADT/STLExtras.h" + +using namespace lldb_private; + +static llvm::Optional<uint32_t> +getNoteType(const llvm::Triple &Triple, + llvm::ArrayRef<RegsetDesc> RegsetDescs) { + for (const auto &Entry : RegsetDescs) { + if (Entry.OS != Triple.getOS()) + continue; + if (Entry.Arch != llvm::Triple::UnknownArch && + Entry.Arch != Triple.getArch()) + continue; + return Entry.Note; + } + return llvm::None; +} + +DataExtractor lldb_private::getRegset(llvm::ArrayRef<CoreNote> Notes, + const llvm::Triple &Triple, + llvm::ArrayRef<RegsetDesc> RegsetDescs) { + auto TypeOr = getNoteType(Triple, RegsetDescs); + if (!TypeOr) + return DataExtractor(); + uint32_t Type = *TypeOr; + auto Iter = llvm::find_if( + Notes, [Type](const CoreNote &Note) { return Note.info.n_type == Type; }); + return Iter == Notes.end() ? DataExtractor() : Iter->data; +} diff --git a/source/Plugins/Process/elf-core/RegisterUtilities.h b/source/Plugins/Process/elf-core/RegisterUtilities.h new file mode 100644 index 0000000000000..9170d94c04b6d --- /dev/null +++ b/source/Plugins/Process/elf-core/RegisterUtilities.h @@ -0,0 +1,110 @@ +//===-- RegisterUtilities.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_REGISTERUTILITIES_H +#define LLDB_REGISTERUTILITIES_H + +#include "Plugins/ObjectFile/ELF/ObjectFileELF.h" +#include "lldb/Utility/DataExtractor.h" + +namespace lldb_private { +/// Core files PT_NOTE segment descriptor types + +namespace FREEBSD { +enum { + NT_PRSTATUS = 1, + NT_FPREGSET, + NT_PRPSINFO, + NT_THRMISC = 7, + NT_PROCSTAT_AUXV = 16, + NT_PPC_VMX = 0x100 +}; +} + +namespace NETBSD { +enum { NT_PROCINFO = 1, NT_AUXV, NT_AMD64_REGS = 33, NT_AMD64_FPREGS = 35 }; +} + +namespace OPENBSD { +enum { + NT_PROCINFO = 10, + NT_AUXV = 11, + NT_REGS = 20, + NT_FPREGS = 21, +}; +} + +namespace LINUX { +enum { + NT_PRSTATUS = 1, + NT_FPREGSET, + NT_PRPSINFO, + NT_TASKSTRUCT, + NT_PLATFORM, + NT_AUXV, + NT_FILE = 0x46494c45, + NT_SIGINFO = 0x53494749, + NT_PPC_VMX = 0x100, + NT_PPC_VSX = 0x102, + NT_PRXFPREG = 0x46e62b7f, +}; +} + +struct CoreNote { + ELFNote info; + DataExtractor data; +}; + +// A structure describing how to find a register set in a core file from a given +// OS. +struct RegsetDesc { + // OS to which this entry applies to. Must not be UnknownOS. + llvm::Triple::OSType OS; + + // Architecture to which this entry applies to. Can be UnknownArch, in which + // case it applies to all architectures of a given OS. + llvm::Triple::ArchType Arch; + + // The note type under which the register set can be found. + uint32_t Note; +}; + +// Returns the register set in Notes which corresponds to the specified Triple +// according to the list of register set descriptions in RegsetDescs. The list +// is scanned linearly, so you can use a more specific entry (e.g. linux-i386) +// to override a more general entry (e.g. general linux), as long as you place +// it earlier in the list. If a register set is not found, it returns an empty +// DataExtractor. +DataExtractor getRegset(llvm::ArrayRef<CoreNote> Notes, + const llvm::Triple &Triple, + llvm::ArrayRef<RegsetDesc> RegsetDescs); + +constexpr RegsetDesc FPR_Desc[] = { + {llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, FREEBSD::NT_FPREGSET}, + // In a i386 core file NT_FPREGSET is present, but it's not the result + // of the FXSAVE instruction like in 64 bit files. + // The result from FXSAVE is in NT_PRXFPREG for i386 core files + {llvm::Triple::Linux, llvm::Triple::x86, LINUX::NT_PRXFPREG}, + {llvm::Triple::Linux, llvm::Triple::UnknownArch, LINUX::NT_FPREGSET}, + {llvm::Triple::NetBSD, llvm::Triple::x86_64, NETBSD::NT_AMD64_FPREGS}, + {llvm::Triple::OpenBSD, llvm::Triple::UnknownArch, OPENBSD::NT_FPREGS}, +}; + +constexpr RegsetDesc PPC_VMX_Desc[] = { + {llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, FREEBSD::NT_PPC_VMX}, + {llvm::Triple::Linux, llvm::Triple::UnknownArch, LINUX::NT_PPC_VMX}, +}; + +constexpr RegsetDesc PPC_VSX_Desc[] = { + {llvm::Triple::Linux, llvm::Triple::UnknownArch, LINUX::NT_PPC_VSX}, +}; + +} // namespace lldb_private + +#endif // #ifndef LLDB_REGISTERUTILITIES_H diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp index 096c20363c78b..10c1ed288b2c5 100644 --- a/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -18,9 +18,9 @@ #include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h" -#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h" -#include "Plugins/Process/Utility/RegisterContextLinux_mips.h" #include "Plugins/Process/Utility/RegisterContextLinux_i386.h" +#include "Plugins/Process/Utility/RegisterContextLinux_mips.h" +#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h" #include "Plugins/Process/Utility/RegisterContextLinux_s390x.h" #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" #include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h" @@ -28,11 +28,13 @@ #include "Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h" #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h" #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h" +#include "Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h" #include "ProcessElfCore.h" #include "RegisterContextPOSIXCore_arm.h" #include "RegisterContextPOSIXCore_arm64.h" #include "RegisterContextPOSIXCore_mips64.h" #include "RegisterContextPOSIXCore_powerpc.h" +#include "RegisterContextPOSIXCore_ppc64le.h" #include "RegisterContextPOSIXCore_s390x.h" #include "RegisterContextPOSIXCore_x86_64.h" #include "ThreadElfCore.h" @@ -45,8 +47,7 @@ using namespace lldb_private; //---------------------------------------------------------------------- ThreadElfCore::ThreadElfCore(Process &process, const ThreadData &td) : Thread(process, td.tid), m_thread_name(td.name), m_thread_reg_ctx_sp(), - m_signo(td.signo), m_gpregset_data(td.gpregset), - m_fpregset_data(td.fpregset), m_vregset_data(td.vregset) {} + m_signo(td.signo), m_gpregset_data(td.gpregset), m_notes(td.notes) {} ThreadElfCore::~ThreadElfCore() { DestroyThread(); } @@ -142,6 +143,9 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { case llvm::Triple::mips64: reg_interface = new RegisterContextLinux_mips64(arch); break; + case llvm::Triple::ppc64le: + reg_interface = new RegisterInfoPOSIX_ppc64le(arch); + break; case llvm::Triple::systemz: reg_interface = new RegisterContextLinux_s390x(arch); break; @@ -191,36 +195,39 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { switch (arch.GetMachine()) { case llvm::Triple::aarch64: m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm64( - *this, reg_interface, m_gpregset_data, m_fpregset_data)); + *this, reg_interface, m_gpregset_data, m_notes)); break; case llvm::Triple::arm: m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm( - *this, reg_interface, m_gpregset_data, m_fpregset_data)); + *this, reg_interface, m_gpregset_data, m_notes)); break; case llvm::Triple::mipsel: case llvm::Triple::mips: m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64( - *this, reg_interface, m_gpregset_data, m_fpregset_data)); + *this, reg_interface, m_gpregset_data, m_notes)); break; case llvm::Triple::mips64: case llvm::Triple::mips64el: m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64( - *this, reg_interface, m_gpregset_data, m_fpregset_data)); + *this, reg_interface, m_gpregset_data, m_notes)); 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_vregset_data)); + *this, reg_interface, m_gpregset_data, m_notes)); + break; + case llvm::Triple::ppc64le: + m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_ppc64le( + *this, reg_interface, m_gpregset_data, m_notes)); break; case llvm::Triple::systemz: m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_s390x( - *this, reg_interface, m_gpregset_data, m_fpregset_data)); + *this, reg_interface, m_gpregset_data, m_notes)); break; case llvm::Triple::x86: case llvm::Triple::x86_64: m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64( - *this, reg_interface, m_gpregset_data, m_fpregset_data)); + *this, reg_interface, m_gpregset_data, m_notes)); break; default: break; @@ -249,7 +256,7 @@ ELFLinuxPrStatus::ELFLinuxPrStatus() { memset(this, 0, sizeof(ELFLinuxPrStatus)); } -size_t ELFLinuxPrStatus::GetSize(lldb_private::ArchSpec &arch) { +size_t ELFLinuxPrStatus::GetSize(const lldb_private::ArchSpec &arch) { constexpr size_t mips_linux_pr_status_size_o32 = 96; constexpr size_t mips_linux_pr_status_size_n32 = 72; if (arch.IsMIPS()) { @@ -265,6 +272,7 @@ size_t ELFLinuxPrStatus::GetSize(lldb_private::ArchSpec &arch) { switch (arch.GetCore()) { case lldb_private::ArchSpec::eCore_s390x_generic: case lldb_private::ArchSpec::eCore_x86_64_x86_64: + case lldb_private::ArchSpec::eCore_ppc64le_generic: return sizeof(ELFLinuxPrStatus); case lldb_private::ArchSpec::eCore_x86_32_i386: case lldb_private::ArchSpec::eCore_x86_32_i486: @@ -274,7 +282,8 @@ size_t ELFLinuxPrStatus::GetSize(lldb_private::ArchSpec &arch) { } } -Status ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch) { +Status ELFLinuxPrStatus::Parse(const DataExtractor &data, + const ArchSpec &arch) { Status error; if (GetSize(arch) > data.GetByteSize()) { error.SetErrorStringWithFormat( @@ -323,7 +332,7 @@ ELFLinuxPrPsInfo::ELFLinuxPrPsInfo() { memset(this, 0, sizeof(ELFLinuxPrPsInfo)); } -size_t ELFLinuxPrPsInfo::GetSize(lldb_private::ArchSpec &arch) { +size_t ELFLinuxPrPsInfo::GetSize(const lldb_private::ArchSpec &arch) { constexpr size_t mips_linux_pr_psinfo_size_o32_n32 = 128; if (arch.IsMIPS()) { uint8_t address_byte_size = arch.GetAddressByteSize(); @@ -344,7 +353,8 @@ size_t ELFLinuxPrPsInfo::GetSize(lldb_private::ArchSpec &arch) { } } -Status ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch) { +Status ELFLinuxPrPsInfo::Parse(const DataExtractor &data, + const ArchSpec &arch) { Status error; ByteOrder byteorder = data.GetByteOrder(); if (GetSize(arch) > data.GetByteSize()) { @@ -413,7 +423,7 @@ size_t ELFLinuxSigInfo::GetSize(const lldb_private::ArchSpec &arch) { } } -Status ELFLinuxSigInfo::Parse(DataExtractor &data, const ArchSpec &arch) { +Status ELFLinuxSigInfo::Parse(const DataExtractor &data, const ArchSpec &arch) { Status error; if (GetSize(arch) > data.GetByteSize()) { error.SetErrorStringWithFormat( diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.h b/source/Plugins/Process/elf-core/ThreadElfCore.h index 5218754137158..335f698dbb248 100644 --- a/source/Plugins/Process/elf-core/ThreadElfCore.h +++ b/source/Plugins/Process/elf-core/ThreadElfCore.h @@ -10,14 +10,11 @@ #ifndef liblldb_ThreadElfCore_h_ #define liblldb_ThreadElfCore_h_ -// C Includes -// C++ Includes -#include <string> - -// Other libraries and framework includes -// Project includes +#include "Plugins/Process/elf-core/RegisterUtilities.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/DataExtractor.h" +#include "llvm/ADT/DenseMap.h" +#include <string> struct compat_timeval { alignas(8) uint64_t tv_sec; @@ -57,15 +54,15 @@ struct ELFLinuxPrStatus { ELFLinuxPrStatus(); - lldb_private::Status Parse(lldb_private::DataExtractor &data, - lldb_private::ArchSpec &arch); + lldb_private::Status Parse(const lldb_private::DataExtractor &data, + const lldb_private::ArchSpec &arch); // Return the bytesize of the structure // 64 bit - just sizeof // 32 bit - hardcoded because we are reusing the struct, but some of the // members are smaller - // so the layout is not the same - static size_t GetSize(lldb_private::ArchSpec &arch); + static size_t GetSize(const lldb_private::ArchSpec &arch); }; static_assert(sizeof(ELFLinuxPrStatus) == 112, @@ -78,7 +75,7 @@ struct ELFLinuxSigInfo { ELFLinuxSigInfo(); - lldb_private::Status Parse(lldb_private::DataExtractor &data, + lldb_private::Status Parse(const lldb_private::DataExtractor &data, const lldb_private::ArchSpec &arch); // Return the bytesize of the structure @@ -113,15 +110,15 @@ struct ELFLinuxPrPsInfo { ELFLinuxPrPsInfo(); - lldb_private::Status Parse(lldb_private::DataExtractor &data, - lldb_private::ArchSpec &arch); + lldb_private::Status Parse(const lldb_private::DataExtractor &data, + const lldb_private::ArchSpec &arch); // Return the bytesize of the structure // 64 bit - just sizeof // 32 bit - hardcoded because we are reusing the struct, but some of the // members are smaller - // so the layout is not the same - static size_t GetSize(lldb_private::ArchSpec &arch); + static size_t GetSize(const lldb_private::ArchSpec &arch); }; static_assert(sizeof(ELFLinuxPrPsInfo) == 136, @@ -129,8 +126,7 @@ static_assert(sizeof(ELFLinuxPrPsInfo) == 136, struct ThreadData { lldb_private::DataExtractor gpregset; - lldb_private::DataExtractor fpregset; - lldb_private::DataExtractor vregset; + std::vector<lldb_private::CoreNote> notes; lldb::tid_t tid; int signo = 0; int prstatus_sig = 0; @@ -177,8 +173,7 @@ protected: int m_signo; lldb_private::DataExtractor m_gpregset_data; - lldb_private::DataExtractor m_fpregset_data; - lldb_private::DataExtractor m_vregset_data; + std::vector<lldb_private::CoreNote> m_notes; bool CalculateStopInfo() override; }; diff --git a/source/Plugins/Process/gdb-remote/CMakeLists.txt b/source/Plugins/Process/gdb-remote/CMakeLists.txt index 5e51feef1d3f8..7ae25f83c5f8a 100644 --- a/source/Plugins/Process/gdb-remote/CMakeLists.txt +++ b/source/Plugins/Process/gdb-remote/CMakeLists.txt @@ -7,6 +7,10 @@ set(LLDB_PLUGINS lldbPluginPlatformMacOSX ) +if(HAVE_LIBCOMPRESSION) + set(LIBCOMPRESSION compression) +endif() + add_lldb_library(lldbPluginProcessGDBRemote PLUGIN GDBRemoteClientBase.cpp GDBRemoteCommunication.cpp @@ -30,6 +34,7 @@ add_lldb_library(lldbPluginProcessGDBRemote PLUGIN lldbTarget lldbUtility ${LLDB_PLUGINS} + ${LIBCOMPRESSION} LINK_COMPONENTS Support ) diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 0c4df7e3f3065..949cf19db658a 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -600,10 +600,9 @@ bool GDBRemoteCommunication::DecompressPacket() { #if defined(HAVE_LIBCOMPRESSION) // libcompression is weak linked so check that compression_decode_buffer() is // available - if (compression_decode_buffer != NULL && - (m_compression_type == CompressionType::ZlibDeflate || - m_compression_type == CompressionType::LZFSE || - m_compression_type == CompressionType::LZ4)) { + if (m_compression_type == CompressionType::ZlibDeflate || + m_compression_type == CompressionType::LZFSE || + m_compression_type == CompressionType::LZ4) { compression_algorithm compression_type; if (m_compression_type == CompressionType::LZFSE) compression_type = COMPRESSION_LZFSE; @@ -815,7 +814,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, // checksum if (m_bytes[0] == '$' && total_length > 4) { for (size_t i = 0; !binary && i < total_length; ++i) { - if (isprint(m_bytes[i]) == 0 && isspace(m_bytes[i]) == 0) { + unsigned char c = m_bytes[i]; + if (isprint(c) == 0 && isspace(c) == 0) { binary = true; } } @@ -1375,3 +1375,39 @@ void GDBRemoteCommunication::AppendBytesToCache(const uint8_t *bytes, } } } + +void llvm::format_provider<GDBRemoteCommunication::PacketResult>::format( + const GDBRemoteCommunication::PacketResult &result, raw_ostream &Stream, + StringRef Style) { + using PacketResult = GDBRemoteCommunication::PacketResult; + + switch (result) { + case PacketResult::Success: + Stream << "Success"; + break; + case PacketResult::ErrorSendFailed: + Stream << "ErrorSendFailed"; + break; + case PacketResult::ErrorSendAck: + Stream << "ErrorSendAck"; + break; + case PacketResult::ErrorReplyFailed: + Stream << "ErrorReplyFailed"; + break; + case PacketResult::ErrorReplyTimeout: + Stream << "ErrorReplyTimeout"; + break; + case PacketResult::ErrorReplyInvalid: + Stream << "ErrorReplyInvalid"; + break; + case PacketResult::ErrorReplyAck: + Stream << "ErrorReplyAck"; + break; + case PacketResult::ErrorDisconnected: + Stream << "ErrorDisconnected"; + break; + case PacketResult::ErrorNoSequenceLock: + Stream << "ErrorNoSequenceLock"; + break; + } +} diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index ce90de3e8470e..ecc9386e49c7d 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -290,4 +290,14 @@ private: } // namespace process_gdb_remote } // namespace lldb_private +namespace llvm { +template <> +struct format_provider< + lldb_private::process_gdb_remote::GDBRemoteCommunication::PacketResult> { + static void format(const lldb_private::process_gdb_remote:: + GDBRemoteCommunication::PacketResult &state, + raw_ostream &Stream, StringRef Style); +}; +} // namespace llvm + #endif // liblldb_GDBRemoteCommunication_h_ diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index e6fd386b903b8..867f57c475cec 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -1022,10 +1022,7 @@ void GDBRemoteCommunicationClient::MaybeEnableCompression( std::string avail_name; #if defined(HAVE_LIBCOMPRESSION) - // libcompression is weak linked so test if compression_decode_buffer() is - // available - if (compression_decode_buffer != NULL && - avail_type == CompressionType::None) { + if (avail_type == CompressionType::None) { for (auto compression : supported_compressions) { if (compression == "lzfse") { avail_type = CompressionType::LZFSE; @@ -1037,10 +1034,7 @@ void GDBRemoteCommunicationClient::MaybeEnableCompression( #endif #if defined(HAVE_LIBCOMPRESSION) - // libcompression is weak linked so test if compression_decode_buffer() is - // available - if (compression_decode_buffer != NULL && - avail_type == CompressionType::None) { + if (avail_type == CompressionType::None) { for (auto compression : supported_compressions) { if (compression == "zlib-deflate") { avail_type = CompressionType::ZlibDeflate; @@ -1064,10 +1058,7 @@ void GDBRemoteCommunicationClient::MaybeEnableCompression( #endif #if defined(HAVE_LIBCOMPRESSION) - // libcompression is weak linked so test if compression_decode_buffer() is - // available - if (compression_decode_buffer != NULL && - avail_type == CompressionType::None) { + if (avail_type == CompressionType::None) { for (auto compression : supported_compressions) { if (compression == "lz4") { avail_type = CompressionType::LZ4; @@ -1079,10 +1070,7 @@ void GDBRemoteCommunicationClient::MaybeEnableCompression( #endif #if defined(HAVE_LIBCOMPRESSION) - // libcompression is weak linked so test if compression_decode_buffer() is - // available - if (compression_decode_buffer != NULL && - avail_type == CompressionType::None) { + if (avail_type == CompressionType::None) { for (auto compression : supported_compressions) { if (compression == "lzma") { avail_type = CompressionType::LZMA; @@ -1601,21 +1589,24 @@ GDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction( // and we only want to override this behavior if we have explicitly // received a qHostInfo telling us otherwise if (m_qHostInfo_is_valid != eLazyBoolYes) { - // On targets like MIPS, watchpoint exceptions are always generated - // before the instruction is executed. The connected target may not - // support qHostInfo or qWatchpointSupportInfo packets. + // On targets like MIPS and ppc64le, watchpoint exceptions are always + // generated before the instruction is executed. The connected target + // may not support qHostInfo or qWatchpointSupportInfo packets. if (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel || - atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el) + atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el || + atype == llvm::Triple::ppc64le) after = false; else after = true; } else { - // For MIPS, set m_watchpoints_trigger_after_instruction to eLazyBoolNo - // if it is not calculated before. - if (m_watchpoints_trigger_after_instruction == eLazyBoolCalculate && - (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel || - atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el)) + // For MIPS and ppc64le, set m_watchpoints_trigger_after_instruction to + // eLazyBoolNo if it is not calculated before. + if ((m_watchpoints_trigger_after_instruction == eLazyBoolCalculate && + (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel || + atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el)) || + atype == llvm::Triple::ppc64le) { m_watchpoints_trigger_after_instruction = eLazyBoolNo; + } after = (m_watchpoints_trigger_after_instruction != eLazyBoolNo); } @@ -2624,8 +2615,8 @@ size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs( * tid. * Assume pid=tid=1 in such cases. */ - if (response.IsUnsupportedResponse() && thread_ids.size() == 0 && - IsConnected()) { + if ((response.IsUnsupportedResponse() || response.IsNormalResponse()) && + thread_ids.size() == 0 && IsConnected()) { thread_ids.push_back(1); } } else { @@ -3451,7 +3442,9 @@ ParseModuleSpec(StructuredData::Dictionary *dict) { if (!dict->GetValueForKeyAsString("uuid", string)) return llvm::None; - result.GetUUID().SetFromStringRef(string, string.size()); + if (result.GetUUID().SetFromStringRef(string, string.size() / 2) != + string.size()) + return llvm::None; if (!dict->GetValueForKeyAsInteger("file_offset", integer)) return llvm::None; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 712d85eed082e..ba67b82463987 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -20,10 +20,8 @@ #include <string> #include <vector> -// Other libraries and framework includes -// Project includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Target/Process.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/StreamGDBRemote.h" #include "lldb/Utility/StructuredData.h" diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index f53db502be934..3cf6b8ac07b24 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -403,8 +403,8 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo( match_info.SetMatchAllUsers( Args::StringToBoolean(value, false, &success)); } else if (key.equals("triple")) { - match_info.GetProcessInfo().GetArchitecture().SetTriple( - value.str().c_str(), NULL); + match_info.GetProcessInfo().GetArchitecture() = + HostInfo::GetAugmentedArchSpec(value); } else { success = false; } @@ -973,8 +973,7 @@ GDBRemoteCommunicationServerCommon::Handle_QLaunchArch( const uint32_t bytes_left = packet.GetBytesLeft(); if (bytes_left > 0) { const char *arch_triple = packet.Peek(); - ArchSpec arch_spec(arch_triple, NULL); - m_process_launch_info.SetArchitecture(arch_spec); + m_process_launch_info.SetArchitecture(HostInfo::GetAugmentedArchSpec(arch_triple)); return SendOKResponse(); } return SendErrorResponse(13); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 9294359dbef1c..32741c2404e22 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -204,21 +204,8 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() { }); } -Status -GDBRemoteCommunicationServerLLGS::SetLaunchArguments(const char *const args[], - int argc) { - if ((argc < 1) || !args || !args[0] || !args[0][0]) - return Status("%s: no process command line specified to launch", - __FUNCTION__); - - m_process_launch_info.SetArguments(const_cast<const char **>(args), true); - return Status(); -} - -Status -GDBRemoteCommunicationServerLLGS::SetLaunchFlags(unsigned int launch_flags) { - m_process_launch_info.GetFlags().Set(launch_flags); - return Status(); +void GDBRemoteCommunicationServerLLGS::SetLaunchInfo(const ProcessLaunchInfo &info) { + m_process_launch_info = info; } Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { @@ -244,13 +231,8 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { "process but one already exists"); auto process_or = m_process_factory.Launch(m_process_launch_info, *this, m_mainloop); - if (!process_or) { - Status status(process_or.takeError()); - llvm::errs() << llvm::formatv( - "failed to launch executable `{0}`: {1}", - m_process_launch_info.GetArguments().GetArgumentAtIndex(0), status); - return status; - } + if (!process_or) + return Status(process_or.takeError()); m_debugged_process_up = std::move(*process_or); } @@ -396,12 +378,12 @@ static void AppendHexValue(StreamString &response, const uint8_t *buf, } static void WriteRegisterValueInHexFixedWidth( - StreamString &response, NativeRegisterContextSP ®_ctx_sp, + StreamString &response, NativeRegisterContext ®_ctx, const RegisterInfo ®_info, const RegisterValue *reg_value_p, lldb::ByteOrder byte_order) { RegisterValue reg_value; if (!reg_value_p) { - Status error = reg_ctx_sp->ReadRegister(®_info, reg_value); + Status error = reg_ctx.ReadRegister(®_info, reg_value); if (error.Success()) reg_value_p = ®_value; // else log. @@ -423,9 +405,7 @@ static void WriteRegisterValueInHexFixedWidth( static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); - NativeRegisterContextSP reg_ctx_sp = thread.GetRegisterContext(); - if (!reg_ctx_sp) - return nullptr; + NativeRegisterContext& reg_ctx = thread.GetRegisterContext(); JSONObject::SP register_object_sp = std::make_shared<JSONObject>(); @@ -448,14 +428,14 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { for (const uint32_t *generic_reg_p = k_expedited_registers; *generic_reg_p != LLDB_INVALID_REGNUM; ++generic_reg_p) { - uint32_t reg_num = reg_ctx_sp->ConvertRegisterKindToRegisterNumber( + uint32_t reg_num = reg_ctx.ConvertRegisterKindToRegisterNumber( eRegisterKindGeneric, *generic_reg_p); if (reg_num == LLDB_INVALID_REGNUM) continue; // Target does not support the given register. #endif const RegisterInfo *const reg_info_p = - reg_ctx_sp->GetRegisterInfoAtIndex(reg_num); + reg_ctx.GetRegisterInfoAtIndex(reg_num); if (reg_info_p == nullptr) { if (log) log->Printf( @@ -469,7 +449,7 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { // registers. RegisterValue reg_value; - Status error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value); + Status error = reg_ctx.ReadRegister(reg_info_p, reg_value); if (error.Fail()) { if (log) log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s", @@ -480,7 +460,7 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { } StreamString stream; - WriteRegisterValueInHexFixedWidth(stream, reg_ctx_sp, *reg_info_p, + WriteRegisterValueInHexFixedWidth(stream, reg_ctx, *reg_info_p, ®_value, lldb::eByteOrderBig); register_object_sp->SetObject( @@ -523,16 +503,16 @@ static JSONArray::SP GetJSONThreadsInfo(NativeProcessProtocol &process, // Ensure we can get info on the given thread. uint32_t thread_idx = 0; - for (NativeThreadProtocolSP thread_sp; - (thread_sp = process.GetThreadAtIndex(thread_idx)) != nullptr; + for (NativeThreadProtocol *thread; + (thread = process.GetThreadAtIndex(thread_idx)) != nullptr; ++thread_idx) { - lldb::tid_t tid = thread_sp->GetID(); + lldb::tid_t tid = thread->GetID(); // Grab the reason this thread stopped. struct ThreadStopInfo tid_stop_info; std::string description; - if (!thread_sp->GetStopReason(tid_stop_info, description)) + if (!thread->GetStopReason(tid_stop_info, description)) return nullptr; const int signum = tid_stop_info.details.signal.signo; @@ -548,7 +528,7 @@ static JSONArray::SP GetJSONThreadsInfo(NativeProcessProtocol &process, threads_array_sp->AppendObject(thread_obj_sp); if (!abridged) { - if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread_sp)) + if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread)) thread_obj_sp->SetObject("registers", registers_sp); } @@ -556,7 +536,7 @@ static JSONArray::SP GetJSONThreadsInfo(NativeProcessProtocol &process, if (signum != 0) thread_obj_sp->SetObject("signal", std::make_shared<JSONNumber>(signum)); - const std::string thread_name = thread_sp->GetName(); + const std::string thread_name = thread->GetName(); if (!thread_name.empty()) thread_obj_sp->SetObject("name", std::make_shared<JSONString>(thread_name)); @@ -604,14 +584,14 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( m_debugged_process_up->GetID(), tid); // Ensure we can get info on the given thread. - NativeThreadProtocolSP thread_sp(m_debugged_process_up->GetThreadByID(tid)); - if (!thread_sp) + NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid); + if (!thread) return SendErrorResponse(51); // Grab the reason this thread stopped. struct ThreadStopInfo tid_stop_info; std::string description; - if (!thread_sp->GetStopReason(tid_stop_info, description)) + if (!thread->GetStopReason(tid_stop_info, description)) return SendErrorResponse(52); // FIXME implement register handling for exec'd inferiors. @@ -638,7 +618,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( response.Printf("thread:%" PRIx64 ";", tid); // Include the thread name if there is one. - const std::string thread_name = thread_sp->GetName(); + const std::string thread_name = thread->GetName(); if (!thread_name.empty()) { size_t thread_name_len = thread_name.length(); @@ -665,15 +645,13 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( response.PutCString("threads:"); uint32_t thread_index = 0; - NativeThreadProtocolSP listed_thread_sp; - for (listed_thread_sp = - m_debugged_process_up->GetThreadAtIndex(thread_index); - listed_thread_sp; ++thread_index, - listed_thread_sp = m_debugged_process_up->GetThreadAtIndex( - thread_index)) { + NativeThreadProtocol *listed_thread; + for (listed_thread = m_debugged_process_up->GetThreadAtIndex(thread_index); + listed_thread; ++thread_index, + listed_thread = m_debugged_process_up->GetThreadAtIndex(thread_index)) { if (thread_index > 0) response.PutChar(','); - response.Printf("%" PRIx64, listed_thread_sp->GetID()); + response.Printf("%" PRIx64, listed_thread->GetID()); } response.PutChar(';'); @@ -701,20 +679,18 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( uint32_t i = 0; response.PutCString("thread-pcs"); char delimiter = ':'; - for (NativeThreadProtocolSP thread_sp; - (thread_sp = m_debugged_process_up->GetThreadAtIndex(i)) != nullptr; + for (NativeThreadProtocol *thread; + (thread = m_debugged_process_up->GetThreadAtIndex(i)) != nullptr; ++i) { - NativeRegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext(); - if (!reg_ctx_sp) - continue; + NativeRegisterContext& reg_ctx = thread->GetRegisterContext(); - uint32_t reg_to_read = reg_ctx_sp->ConvertRegisterKindToRegisterNumber( + uint32_t reg_to_read = reg_ctx.ConvertRegisterKindToRegisterNumber( eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); const RegisterInfo *const reg_info_p = - reg_ctx_sp->GetRegisterInfoAtIndex(reg_to_read); + reg_ctx.GetRegisterInfoAtIndex(reg_to_read); RegisterValue reg_value; - Status error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value); + Status error = reg_ctx.ReadRegister(reg_info_p, reg_value); if (error.Fail()) { if (log) log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s", @@ -727,7 +703,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( response.PutChar(delimiter); delimiter = ','; - WriteRegisterValueInHexFixedWidth(response, reg_ctx_sp, *reg_info_p, + WriteRegisterValueInHexFixedWidth(response, reg_ctx, *reg_info_p, ®_value, endian::InlHostByteOrder()); } @@ -739,49 +715,48 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( // // Grab the register context. - NativeRegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext(); - if (reg_ctx_sp) { - // Expedite all registers in the first register set (i.e. should be GPRs) - // that are not contained in other registers. - const RegisterSet *reg_set_p; - if (reg_ctx_sp->GetRegisterSetCount() > 0 && - ((reg_set_p = reg_ctx_sp->GetRegisterSet(0)) != nullptr)) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s expediting registers " - "from set '%s' (registers set count: %zu)", - __FUNCTION__, - reg_set_p->name ? reg_set_p->name : "<unnamed-set>", - reg_set_p->num_registers); - - for (const uint32_t *reg_num_p = reg_set_p->registers; - *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) { - const RegisterInfo *const reg_info_p = - reg_ctx_sp->GetRegisterInfoAtIndex(*reg_num_p); - if (reg_info_p == nullptr) { + NativeRegisterContext& reg_ctx = thread->GetRegisterContext(); + // Expedite all registers in the first register set (i.e. should be GPRs) + // that are not contained in other registers. + const RegisterSet *reg_set_p; + if (reg_ctx.GetRegisterSetCount() > 0 && + ((reg_set_p = reg_ctx.GetRegisterSet(0)) != nullptr)) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s expediting registers " + "from set '%s' (registers set count: %zu)", + __FUNCTION__, + reg_set_p->name ? reg_set_p->name : "<unnamed-set>", + reg_set_p->num_registers); + + for (const uint32_t *reg_num_p = reg_set_p->registers; + *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) { + const RegisterInfo *const reg_info_p = + reg_ctx.GetRegisterInfoAtIndex(*reg_num_p); + if (reg_info_p == nullptr) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to get " + "register info for register set '%s', register index " + "%" PRIu32, + __FUNCTION__, + reg_set_p->name ? reg_set_p->name : "<unnamed-set>", + *reg_num_p); + } else if (reg_info_p->value_regs == nullptr) { + // Only expediate registers that are not contained in other registers. + RegisterValue reg_value; + Status error = reg_ctx.ReadRegister(reg_info_p, reg_value); + if (error.Success()) { + response.Printf("%.02x:", *reg_num_p); + WriteRegisterValueInHexFixedWidth(response, reg_ctx, *reg_info_p, + ®_value, lldb::eByteOrderBig); + response.PutChar(';'); + } else { if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to get " - "register info for register set '%s', register index " - "%" PRIu32, + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to read " + "register '%s' index %" PRIu32 ": %s", __FUNCTION__, - reg_set_p->name ? reg_set_p->name : "<unnamed-set>", - *reg_num_p); - } else if (reg_info_p->value_regs == nullptr) { - // Only expediate registers that are not contained in other registers. - RegisterValue reg_value; - Status error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value); - if (error.Success()) { - response.Printf("%.02x:", *reg_num_p); - WriteRegisterValueInHexFixedWidth(response, reg_ctx_sp, *reg_info_p, - ®_value, lldb::eByteOrderBig); - response.PutChar(';'); - } else { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to read " - "register '%s' index %" PRIu32 ": %s", - __FUNCTION__, reg_info_p->name ? reg_info_p->name - : "<unnamed-register>", - *reg_num_p, error.AsCString()); - } + reg_info_p->name ? reg_info_p->name + : "<unnamed-register>", + *reg_num_p, error.AsCString()); } } } @@ -837,6 +812,7 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited( // We are ready to exit the debug monitor. m_exit_now = true; + m_mainloop.RequestTermination(); } void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped( @@ -1316,12 +1292,12 @@ GDBRemoteCommunicationServerLLGS::Handle_qC(StringExtractorGDBRemote &packet) { lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID(); SetCurrentThreadID(tid); - NativeThreadProtocolSP thread_sp = m_debugged_process_up->GetCurrentThread(); - if (!thread_sp) + NativeThreadProtocol *thread = m_debugged_process_up->GetCurrentThread(); + if (!thread) return SendErrorResponse(69); StreamString response; - response.Printf("QC%" PRIx64, thread_sp->GetID()); + response.Printf("QC%" PRIx64, thread->GetID()); return SendPacketNoLock(response.GetString()); } @@ -1692,14 +1668,12 @@ GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo( return SendErrorResponse(68); // Ensure we have a thread. - NativeThreadProtocolSP thread_sp(m_debugged_process_up->GetThreadAtIndex(0)); - if (!thread_sp) + NativeThreadProtocol *thread = m_debugged_process_up->GetThreadAtIndex(0); + if (!thread) return SendErrorResponse(69); // Get the register context for the first thread. - NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); - if (!reg_context_sp) - return SendErrorResponse(69); + NativeRegisterContext ®_context = thread->GetRegisterContext(); // Parse out the register number from the request. packet.SetFilePos(strlen("qRegisterInfo")); @@ -1710,11 +1684,10 @@ GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo( // Return the end of registers response if we've iterated one past the end of // the register set. - if (reg_index >= reg_context_sp->GetUserRegisterCount()) + if (reg_index >= reg_context.GetUserRegisterCount()) return SendErrorResponse(69); - const RegisterInfo *reg_info = - reg_context_sp->GetRegisterInfoAtIndex(reg_index); + const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index); if (!reg_info) return SendErrorResponse(69); @@ -1796,7 +1769,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo( }; const char *const register_set_name = - reg_context_sp->GetRegisterSetNameForRegisterAtIndex(reg_index); + reg_context.GetRegisterSetNameForRegisterAtIndex(reg_index); if (register_set_name) { response.PutCString("set:"); response.PutCString(register_set_name); @@ -1908,18 +1881,17 @@ GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo( response.PutChar('m'); LLDB_LOG(log, "starting thread iteration"); - NativeThreadProtocolSP thread_sp; + NativeThreadProtocol *thread; uint32_t thread_index; for (thread_index = 0, - thread_sp = m_debugged_process_up->GetThreadAtIndex(thread_index); - thread_sp; ++thread_index, - thread_sp = m_debugged_process_up->GetThreadAtIndex(thread_index)) { - LLDB_LOG(log, "iterated thread {0}({1}, tid={2})", thread_index, - thread_sp ? "is not null" : "null", - thread_sp ? thread_sp->GetID() : LLDB_INVALID_THREAD_ID); + thread = m_debugged_process_up->GetThreadAtIndex(thread_index); + thread; ++thread_index, + thread = m_debugged_process_up->GetThreadAtIndex(thread_index)) { + LLDB_LOG(log, "iterated thread {0}(tid={2})", thread_index, + thread->GetID()); if (thread_index > 0) response.PutChar(','); - response.Printf("%" PRIx64, thread_sp->GetID()); + response.Printf("%" PRIx64, thread->GetID()); } LLDB_LOG(log, "finished thread iteration"); @@ -1951,38 +1923,27 @@ GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) { } // Get the thread to use. - NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet); - if (!thread_sp) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no thread available", - __FUNCTION__); + NativeThreadProtocol *thread = GetThreadFromSuffix(packet); + if (!thread) { + LLDB_LOG(log, "failed, no thread available"); return SendErrorResponse(0x15); } // Get the thread's register context. - NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); - if (!reg_context_sp) { - LLDB_LOG( - log, - "pid {0} tid {1} failed, no register context available for the thread", - m_debugged_process_up->GetID(), thread_sp->GetID()); - return SendErrorResponse(0x15); - } + NativeRegisterContext ®_context = thread->GetRegisterContext(); // Return the end of registers response if we've iterated one past the end of // the register set. - if (reg_index >= reg_context_sp->GetUserRegisterCount()) { + if (reg_index >= reg_context.GetUserRegisterCount()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " "register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, - reg_context_sp->GetUserRegisterCount()); + reg_context.GetUserRegisterCount()); return SendErrorResponse(0x15); } - const RegisterInfo *reg_info = - reg_context_sp->GetRegisterInfoAtIndex(reg_index); + const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index); if (!reg_info) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " @@ -1996,7 +1957,7 @@ GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) { // Retrieve the value RegisterValue reg_value; - Status error = reg_context_sp->ReadRegister(reg_info, reg_value); + Status error = reg_context.ReadRegister(reg_info, reg_value); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, read of " @@ -2047,24 +2008,13 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { return SendIllFormedResponse( packet, "P packet missing '=' char after register number"); - // Get process architecture. - ArchSpec process_arch; - if (!m_debugged_process_up || - !m_debugged_process_up->GetArchitecture(process_arch)) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to retrieve " - "inferior architecture", - __FUNCTION__); - return SendErrorResponse(0x49); - } - // Parse out the value. uint8_t reg_bytes[32]; // big enough to support up to 256 bit ymmN register size_t reg_size = packet.GetHexBytesAvail(reg_bytes); // Get the thread to use. - NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet); - if (!thread_sp) { + NativeThreadProtocol *thread = GetThreadFromSuffix(packet); + if (!thread) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, no thread " "available (thread index 0)", @@ -2073,18 +2023,8 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { } // Get the thread's register context. - NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); - if (!reg_context_sp) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 - " failed, no register context available for the thread", - __FUNCTION__, m_debugged_process_up->GetID(), thread_sp->GetID()); - return SendErrorResponse(0x15); - } - - const RegisterInfo *reg_info = - reg_context_sp->GetRegisterInfoAtIndex(reg_index); + NativeRegisterContext ®_context = thread->GetRegisterContext(); + const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index); if (!reg_info) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " @@ -2095,12 +2035,11 @@ GDBRemoteCommunicationServerLLGS::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->GetUserRegisterCount()) { + if (reg_index >= reg_context.GetUserRegisterCount()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " "register %" PRIu32 " beyond register count %" PRIu32, - __FUNCTION__, reg_index, - reg_context_sp->GetUserRegisterCount()); + __FUNCTION__, reg_index, reg_context.GetUserRegisterCount()); return SendErrorResponse(0x47); } @@ -2115,8 +2054,10 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { // Build the reginfos response. StreamGDBRemote response; - RegisterValue reg_value(reg_bytes, reg_size, process_arch.GetByteOrder()); - Status error = reg_context_sp->WriteRegister(reg_info, reg_value); + RegisterValue reg_value( + reg_bytes, reg_size, + m_debugged_process_up->GetArchitecture().GetByteOrder()); + Status error = reg_context.WriteRegister(reg_info, reg_value); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, write of " @@ -2177,8 +2118,8 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) { // Ensure we have the given thread when not specifying -1 (all threads) or 0 // (any thread). if (tid != LLDB_INVALID_THREAD_ID && tid != 0) { - NativeThreadProtocolSP thread_sp(m_debugged_process_up->GetThreadByID(tid)); - if (!thread_sp) { + NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid); + if (!thread) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64 " not found", @@ -2739,8 +2680,8 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { // Double check that we have such a thread. // TODO investigate: on MacOSX we might need to do an UpdateThreads () here. - NativeThreadProtocolSP thread_sp = m_debugged_process_up->GetThreadByID(tid); - if (!thread_sp || thread_sp->GetID() != tid) + NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid); + if (!thread) return SendErrorResponse(0x33); // Create the step action for the given thread. @@ -2865,8 +2806,8 @@ GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState( packet.SetFilePos(strlen("QSaveRegisterState")); // Get the thread to use. - NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet); - if (!thread_sp) { + NativeThreadProtocol *thread = GetThreadFromSuffix(packet); + if (!thread) { if (m_thread_suffix_supported) return SendIllFormedResponse( packet, "No thread specified in QSaveRegisterState packet"); @@ -2876,18 +2817,11 @@ GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState( } // Grab the register context for the thread. - NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); - if (!reg_context_sp) { - LLDB_LOG( - log, - "pid {0} tid {1} failed, no register context available for the thread", - m_debugged_process_up->GetID(), thread_sp->GetID()); - return SendErrorResponse(0x15); - } + NativeRegisterContext& reg_context = thread->GetRegisterContext(); // Save registers to a buffer. DataBufferSP register_data_sp; - Status error = reg_context_sp->ReadAllRegisterValues(register_data_sp); + Status error = reg_context.ReadAllRegisterValues(register_data_sp); if (error.Fail()) { LLDB_LOG(log, "pid {0} failed to save all register values: {1}", m_debugged_process_up->GetID(), error); @@ -2930,8 +2864,8 @@ GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState( } // Get the thread to use. - NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet); - if (!thread_sp) { + NativeThreadProtocol *thread = GetThreadFromSuffix(packet); + if (!thread) { if (m_thread_suffix_supported) return SendIllFormedResponse( packet, "No thread specified in QRestoreRegisterState packet"); @@ -2941,14 +2875,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState( } // Grab the register context for the thread. - NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); - if (!reg_context_sp) { - LLDB_LOG( - log, - "pid {0} tid {1} failed, no register context available for the thread", - m_debugged_process_up->GetID(), thread_sp->GetID()); - return SendErrorResponse(0x15); - } + NativeRegisterContext ®_context = thread->GetRegisterContext(); // Retrieve register state buffer, then remove from the list. DataBufferSP register_data_sp; @@ -2969,7 +2896,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState( m_saved_registers_map.erase(it); } - Status error = reg_context_sp->WriteAllRegisterValues(register_data_sp); + Status error = reg_context.WriteAllRegisterValues(register_data_sp); if (error.Fail()) { LLDB_LOG(log, "pid {0} failed to restore all register values: {1}", m_debugged_process_up->GetID(), error); @@ -3219,14 +3146,12 @@ void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() { } } -NativeThreadProtocolSP GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( +NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( StringExtractorGDBRemote &packet) { - NativeThreadProtocolSP thread_sp; - // We have no thread if we don't have a process. if (!m_debugged_process_up || m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID) - return thread_sp; + return nullptr; // If the client hasn't asked for thread suffix support, there will not be a // thread suffix. @@ -3234,7 +3159,7 @@ NativeThreadProtocolSP GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( if (!m_thread_suffix_supported) { const lldb::tid_t current_tid = GetCurrentThreadID(); if (current_tid == LLDB_INVALID_THREAD_ID) - return thread_sp; + return nullptr; else if (current_tid == 0) { // Pick a thread. return m_debugged_process_up->GetThreadAtIndex(0); @@ -3251,11 +3176,11 @@ NativeThreadProtocolSP GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( "error: expected ';' prior to start of thread suffix: packet " "contents = '%s'", __FUNCTION__, packet.GetStringRef().c_str()); - return thread_sp; + return nullptr; } if (!packet.GetBytesLeft()) - return thread_sp; + return nullptr; // Parse out thread: portion. if (strncmp(packet.Peek(), "thread:", strlen("thread:")) != 0) { @@ -3264,14 +3189,14 @@ NativeThreadProtocolSP GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( "error: expected 'thread:' but not found, packet contents = " "'%s'", __FUNCTION__, packet.GetStringRef().c_str()); - return thread_sp; + return nullptr; } packet.SetFilePos(packet.GetFilePos() + strlen("thread:")); const lldb::tid_t tid = packet.GetHexMaxU64(false, 0); if (tid != 0) return m_debugged_process_up->GetThreadByID(tid); - return thread_sp; + return nullptr; } lldb::tid_t GDBRemoteCommunicationServerLLGS::GetCurrentThreadID() const { diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index 71199473bb8ed..5a74d1acaa237 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -43,32 +43,7 @@ public: MainLoop &mainloop, const NativeProcessProtocol::Factory &process_factory); - //------------------------------------------------------------------ - /// Specify the program to launch and its arguments. - /// - /// @param[in] args - /// The command line to launch. - /// - /// @param[in] argc - /// The number of elements in the args array of cstring pointers. - /// - /// @return - /// An Status object indicating the success or failure of making - /// the setting. - //------------------------------------------------------------------ - Status SetLaunchArguments(const char *const args[], int argc); - - //------------------------------------------------------------------ - /// Specify the launch flags for the process. - /// - /// @param[in] launch_flags - /// The launch flags to use when launching this process. - /// - /// @return - /// An Status object indicating the success or failure of making - /// the setting. - //------------------------------------------------------------------ - Status SetLaunchFlags(unsigned int launch_flags); + void SetLaunchInfo(const ProcessLaunchInfo &info); //------------------------------------------------------------------ /// Launch a process with the current launch settings. @@ -234,7 +209,7 @@ private: void HandleInferiorState_Stopped(NativeProcessProtocol *process); - NativeThreadProtocolSP GetThreadFromSuffix(StringExtractorGDBRemote &packet); + NativeThreadProtocol *GetThreadFromSuffix(StringExtractorGDBRemote &packet); uint32_t GetNextSavedRegistersID(); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp index 977c34c2a69b3..04ed9d704e137 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp @@ -128,8 +128,9 @@ Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer( llvm::StringRef platform_ip; int platform_port; llvm::StringRef platform_path; - bool ok = UriParser::Parse(GetConnection()->GetURI(), platform_scheme, - platform_ip, platform_port, platform_path); + std::string platform_uri = GetConnection()->GetURI(); + bool ok = UriParser::Parse(platform_uri, platform_scheme, platform_ip, + platform_port, platform_path); UNUSED_IF_ASSERT_DISABLED(ok); assert(ok); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index 612c7144451e0..e418deee01f3d 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -178,7 +178,7 @@ bool GDBRemoteRegisterContext::GetPrimordialRegister( const RegisterInfo *reg_info, GDBRemoteCommunicationClient &gdb_comm) { const uint32_t lldb_reg = reg_info->kinds[eRegisterKindLLDB]; const uint32_t remote_reg = reg_info->kinds[eRegisterKindProcessPlugin]; - StringExtractorGDBRemote response; + if (DataBufferSP buffer_sp = gdb_comm.ReadRegister(m_thread.GetProtocolID(), remote_reg)) return PrivateSetRegisterValue( diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index be11dd9bc7ec7..35d02c15ab85b 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -29,7 +29,6 @@ #include <sstream> #include "lldb/Breakpoint/Watchpoint.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" @@ -244,7 +243,7 @@ bool ProcessGDBRemote::CanDebug(lldb::TargetSP target_sp, //---------------------------------------------------------------------- ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, ListenerSP listener_sp) - : Process(target_sp, listener_sp), m_flags(0), m_gdb_comm(), + : Process(target_sp, listener_sp), m_debugserver_pid(LLDB_INVALID_PROCESS_ID), m_last_stop_packet_mutex(), m_register_info(), m_async_broadcaster(NULL, "lldb.process.gdb-remote.async-broadcaster"), @@ -818,7 +817,7 @@ Status ProcessGDBRemote::DoLaunch(Module *exe_module, if (object_file) { error = EstablishConnectionIfNeeded(launch_info); if (error.Success()) { - lldb_utility::PseudoTerminal pty; + PseudoTerminal pty; const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0; PlatformSP platform_sp(GetTarget().GetPlatform()); @@ -947,8 +946,7 @@ Status ProcessGDBRemote::DoLaunch(Module *exe_module, SetPrivateState(SetThreadStopInfo(response)); if (!disable_stdio) { - if (pty.GetMasterFileDescriptor() != - lldb_utility::PseudoTerminal::invalid_fd) + if (pty.GetMasterFileDescriptor() != PseudoTerminal::invalid_fd) SetSTDIOFileDescriptor(pty.ReleaseMasterFileDescriptor()); } } @@ -3255,7 +3253,6 @@ Status ProcessGDBRemote::DisableWatchpoint(Watchpoint *wp, bool notify) { } void ProcessGDBRemote::Clear() { - m_flags = 0; m_thread_list_real.Clear(); m_thread_list.Clear(); } @@ -3289,7 +3286,7 @@ ProcessGDBRemote::EstablishConnectionIfNeeded(const ProcessInfo &process_info) { } return error; } -#if defined(__APPLE__) +#if !defined(_WIN32) #define USE_SOCKETPAIR_FOR_LOCAL_CONNECTION 1 #endif @@ -3333,8 +3330,8 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver( lldb_utility::CleanUp<int, int> our_socket(-1, -1, close); lldb_utility::CleanUp<int, int> gdb_socket(-1, -1, close); - // Use a socketpair on Apple for now until other platforms can verify it - // works and is fast enough + // Use a socketpair on non-Windows systems for security and performance + // reasons. { int sockets[2]; /* the pair of socket descriptors */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) { @@ -4168,7 +4165,6 @@ struct GdbServerTargetInfo { std::string osabi; stringVec includes; RegisterSetMap reg_set_map; - XMLNode feature_node; }; bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, @@ -4374,8 +4370,8 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) { XMLNode target_node = xml_document.GetRootElement("target"); if (target_node) { - XMLNode feature_node; - target_node.ForEachChildElement([&target_info, &feature_node]( + std::vector<XMLNode> feature_nodes; + target_node.ForEachChildElement([&target_info, &feature_nodes]( const XMLNode &node) -> bool { llvm::StringRef name = node.GetName(); if (name == "architecture") { @@ -4387,7 +4383,7 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) { if (!href.empty()) target_info.includes.push_back(href.str()); } else if (name == "feature") { - feature_node = node; + feature_nodes.push_back(node); } else if (name == "groups") { node.ForEachChildElementWithName( "group", [&target_info](const XMLNode &node) -> bool { @@ -4423,7 +4419,7 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) { // set the Target's architecture yet, so the ABI is also potentially // incorrect. ABISP abi_to_use_sp = ABI::FindPlugin(shared_from_this(), arch_to_use); - if (feature_node) { + for (auto &feature_node : feature_nodes) { ParseRegisters(feature_node, target_info, this->m_register_info, abi_to_use_sp, cur_reg_num, reg_offset); } diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 54a472d7332e0..42d1c4ecd6663 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -18,9 +18,6 @@ #include <string> #include <vector> -// Other libraries and framework includes -// Project includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Broadcaster.h" #include "lldb/Core/LoadedModuleInfoList.h" #include "lldb/Core/ModuleSpec.h" @@ -28,6 +25,7 @@ #include "lldb/Host/HostThread.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamGDBRemote.h" @@ -263,7 +261,6 @@ protected: eBroadcastBitAsyncThreadDidExit = (1 << 2) }; - Flags m_flags; // Process specific flags (see eFlags enums) GDBRemoteCommunicationClient m_gdb_comm; std::atomic<lldb::pid_t> m_debugserver_pid; std::vector<StringExtractorGDBRemote> m_stop_packet_stack; // The stop packet @@ -324,10 +321,6 @@ protected: void Clear(); - Flags &GetFlags() { return m_flags; } - - const Flags &GetFlags() const { return m_flags; } - bool UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) override; diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index 5197e8f9adfcc..27dd03bfc7bc5 100644 --- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -10,7 +10,6 @@ #include "ThreadGDBRemote.h" #include "lldb/Breakpoint/Watchpoint.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/State.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" diff --git a/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/source/Plugins/Process/mach-core/ProcessMachCore.cpp index a6178500dfc5c..d21651b77ee0c 100644 --- a/source/Plugins/Process/mach-core/ProcessMachCore.cpp +++ b/source/Plugins/Process/mach-core/ProcessMachCore.cpp @@ -468,7 +468,7 @@ Status ProcessMachCore::DoLoadCore() { // it to match the core file which is always single arch. ArchSpec arch(m_core_module_sp->GetArchitecture()); if (arch.GetCore() == ArchSpec::eCore_x86_32_i486) { - arch.SetTriple("i386", GetTarget().GetPlatform().get()); + arch = Platform::GetAugmentedArchSpec(GetTarget().GetPlatform().get(), "i386"); } if (arch.IsValid()) GetTarget().SetArchitecture(arch); diff --git a/source/Plugins/Process/mach-core/ThreadMachCore.cpp b/source/Plugins/Process/mach-core/ThreadMachCore.cpp index 3917b99bd63d5..2b44105c13b1a 100644 --- a/source/Plugins/Process/mach-core/ThreadMachCore.cpp +++ b/source/Plugins/Process/mach-core/ThreadMachCore.cpp @@ -12,7 +12,6 @@ #include "lldb/Utility/SafeMachO.h" #include "lldb/Breakpoint/Watchpoint.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/State.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Process.h" @@ -20,6 +19,7 @@ #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/Unwind.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/StreamString.h" diff --git a/source/Plugins/Process/minidump/MinidumpParser.h b/source/Plugins/Process/minidump/MinidumpParser.h index df6deb482afdb..b7329ffc00289 100644 --- a/source/Plugins/Process/minidump/MinidumpParser.h +++ b/source/Plugins/Process/minidump/MinidumpParser.h @@ -14,8 +14,7 @@ // Project includes #include "MinidumpTypes.h" -// Other libraries and framework includes -#include "lldb/Core/ArchSpec.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/Status.h" diff --git a/source/Plugins/Process/minidump/ProcessMinidump.h b/source/Plugins/Process/minidump/ProcessMinidump.h index d5c46be97352e..4b91d1ba396a4 100644 --- a/source/Plugins/Process/minidump/ProcessMinidump.h +++ b/source/Plugins/Process/minidump/ProcessMinidump.h @@ -82,6 +82,14 @@ public: bool GetProcessInfo(ProcessInstanceInfo &info) override; + Status WillResume() override { + Status error; + error.SetErrorStringWithFormat( + "error: %s does not support resuming processes", + GetPluginName().GetCString()); + return error; + } + MinidumpParser m_minidump_parser; protected: diff --git a/source/Plugins/Process/minidump/ThreadMinidump.cpp b/source/Plugins/Process/minidump/ThreadMinidump.cpp index 9c21cc92376fc..3fafb6134e7f6 100644 --- a/source/Plugins/Process/minidump/ThreadMinidump.cpp +++ b/source/Plugins/Process/minidump/ThreadMinidump.cpp @@ -17,8 +17,8 @@ // Other libraries and framework includes #include "Plugins/Process/Utility/RegisterContextLinux_i386.h" #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" - #include "Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StopInfo.h" @@ -43,8 +43,6 @@ ThreadMinidump::~ThreadMinidump() {} void ThreadMinidump::RefreshStateAfterStop() {} -void ThreadMinidump::ClearStackFrames() {} - RegisterContextSP ThreadMinidump::GetRegisterContext() { if (!m_reg_context_sp) { m_reg_context_sp = CreateRegisterContextForFrame(nullptr); @@ -76,20 +74,18 @@ ThreadMinidump::CreateRegisterContextForFrame(StackFrame *frame) { reg_interface = new RegisterContextLinux_i386(arch); lldb::DataBufferSP buf = ConvertMinidumpContext_x86_32(m_gpregset_data, reg_interface); - DataExtractor gpregs(buf, lldb::eByteOrderLittle, 4); - DataExtractor fpregs; + DataExtractor gpregset(buf, lldb::eByteOrderLittle, 4); m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64( - *this, reg_interface, gpregs, fpregs)); + *this, reg_interface, gpregset, {})); break; } case llvm::Triple::x86_64: { reg_interface = new RegisterContextLinux_x86_64(arch); lldb::DataBufferSP buf = ConvertMinidumpContext_x86_64(m_gpregset_data, reg_interface); - DataExtractor gpregs(buf, lldb::eByteOrderLittle, 8); - DataExtractor fpregs; + DataExtractor gpregset(buf, lldb::eByteOrderLittle, 8); m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64( - *this, reg_interface, gpregs, fpregs)); + *this, reg_interface, gpregset, {})); break; } default: diff --git a/source/Plugins/Process/minidump/ThreadMinidump.h b/source/Plugins/Process/minidump/ThreadMinidump.h index 97db452edfffa..74ac44f74dcf6 100644 --- a/source/Plugins/Process/minidump/ThreadMinidump.h +++ b/source/Plugins/Process/minidump/ThreadMinidump.h @@ -37,8 +37,6 @@ public: lldb::RegisterContextSP CreateRegisterContextForFrame(StackFrame *frame) override; - void ClearStackFrames() override; - protected: lldb::RegisterContextSP m_thread_reg_ctx_sp; llvm::ArrayRef<uint8_t> m_gpregset_data; diff --git a/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp b/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp index f1450c31b36b9..8424b55ee69cd 100644 --- a/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp +++ b/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp @@ -857,36 +857,6 @@ protected: *static_cast<StructuredDataDarwinLog *>(plugin_sp.get()); if (m_enable) { -// To do this next part right, we need to track whether we -// added the proper environment variable at launch time. -// It is incorrect to assume that we're enabling after launch, -// and that therefore if we needed the env var set to properly -// handle the options, that it is set incorrectly. The env var -// could have been added if this is a re-enable using different -// arguments. This is a bit tricky as the point where we -// have to set the env var, we don't yet have a process or the -// associated darwin-log plugin instance, and thus don't have a -// great place to stick this knowledge. -#if 0 - // Check if we're attempting to disable debug-level or - // info-level content but we haven't launched with the magic - // env var that suppresses the "always add" of those. In - // that scenario, the user is asking *not* to see debug or - // info level messages, but will see them anyway. Warn and - // show how to correct it. - if (!m_options_sp->GetIncludeDebugLevel() && - !GetGlobalProperties()->GetUseStrictSources()) - { - AppendStrictSourcesWarning(result, "debug-level"); - } - - if (!m_options_sp->GetIncludeInfoLevel() && - !GetGlobalProperties()->GetUseStrictSources()) - { - AppendStrictSourcesWarning(result, "info-level"); - } -#endif - // Hook up the breakpoint for the process that detects when // libtrace has been sufficiently initialized to really start // the os_log stream. This is insurance to assure us that @@ -1823,34 +1793,10 @@ StructuredDataDarwinLog::DumpHeader(Stream &output_stream, if (header_count > 0) stream.PutChar(','); -// Switch over to the #if 0 branch once we figure out -// how we want to present settings for the tri-state of -// no-activity, activity (most derived only), or activity-chain. -#if 1 // Display the activity chain, from parent-most to child-most // activity, separated by a colon (:). stream.PutCString("activity-chain="); stream.PutCString(activity_chain); -#else - if (GetGlobalProperties()->GetDisplayActivityChain()) { - // Display the activity chain, from parent-most to child-most - // activity, separated by a colon (:). - stream.PutCString("activity-chain="); - stream.PutCString(activity_chain.c_str()); - } else { - // We're only displaying the child-most activity. - stream.PutCString("activity="); - auto pos = activity_chain.find_last_of(':'); - if (pos == std::string::npos) { - // The activity chain only has one level, use the whole - // thing. - stream.PutCString(activity_chain.c_str()); - } else { - // Display everything after the final ':'. - stream.PutCString(activity_chain.substr(pos + 1).c_str()); - } - } -#endif ++header_count; } } diff --git a/source/Plugins/SymbolFile/DWARF/CMakeLists.txt b/source/Plugins/SymbolFile/DWARF/CMakeLists.txt index fb468440f9e03..05d9e66428680 100644 --- a/source/Plugins/SymbolFile/DWARF/CMakeLists.txt +++ b/source/Plugins/SymbolFile/DWARF/CMakeLists.txt @@ -30,6 +30,8 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN NameToDIE.cpp SymbolFileDWARF.cpp SymbolFileDWARFDwo.cpp + SymbolFileDWARFDwoDwp.cpp + SymbolFileDWARFDwp.cpp SymbolFileDWARFDebugMap.cpp UniqueDWARFASTType.cpp @@ -47,5 +49,6 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN lldbPluginCPlusPlusLanguage lldbPluginExpressionParserClang LINK_COMPONENTS + DebugInfoDWARF Support ) diff --git a/source/Plugins/SymbolFile/DWARF/DIERef.cpp b/source/Plugins/SymbolFile/DWARF/DIERef.cpp index 5ed9c6ab72825..c05444c031e67 100644 --- a/source/Plugins/SymbolFile/DWARF/DIERef.cpp +++ b/source/Plugins/SymbolFile/DWARF/DIERef.cpp @@ -65,7 +65,7 @@ lldb::user_id_t DIERef::GetUID(SymbolFileDWARF *dwarf) const { // // SymbolFileDWARFDwo sets the ID to the compile unit offset. //---------------------------------------------------------------------- - if (dwarf) + if (dwarf && die_offset != DW_INVALID_OFFSET) return dwarf->GetID() | die_offset; else return LLDB_INVALID_UID; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index f5418763d67be..6ae2b225d8696 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -786,7 +786,17 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, m_ast.ParseClassTemplateDecl(decl_ctx, accessibility, type_name_cstr, tag_decl_kind, template_param_infos); - + if (!class_template_decl) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" " + "clang::ClassTemplateDecl failed to return a decl.", + static_cast<void *>(this), die.GetOffset(), + DW_TAG_value_to_name(tag), type_name_cstr); + } + return TypeSP(); + } + clang::ClassTemplateSpecializationDecl *class_specialization_decl = m_ast.CreateClassTemplateSpecializationDecl( @@ -927,6 +937,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, // Set a bit that lets us know that we are currently parsing this dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + bool is_scoped = false; DWARFFormValue encoding_form; const size_t num_attributes = die.GetAttributes(attributes); @@ -963,6 +974,9 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, case DW_AT_declaration: is_forward_declaration = form_value.Boolean(); break; + case DW_AT_enum_class: + is_scoped = form_value.Boolean(); + break; case DW_AT_allocated: case DW_AT_associated: case DW_AT_bit_stride: @@ -1052,7 +1066,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, clang_type = m_ast.CreateEnumerationType( type_name_cstr, GetClangDeclContextContainingDIE(die, nullptr), - decl, enumerator_clang_type); + decl, enumerator_clang_type, is_scoped); } else { enumerator_clang_type = m_ast.GetEnumerationIntegerType(clang_type.GetOpaqueQualType()); @@ -2741,8 +2755,6 @@ bool DWARFASTParserClang::ParseChildMembers( form_value.BlockData() - debug_info_data.GetDataStart(); if (DWARFExpression::Evaluate( nullptr, // ExecutionContext * - nullptr, // ClangExpressionVariableList * - nullptr, // ClangExpressionDeclMap * nullptr, // RegisterContext * module_sp, debug_info_data, die.GetCU(), block_offset, block_length, eRegisterKindDWARF, &initialValue, @@ -3214,11 +3226,11 @@ bool DWARFASTParserClang::ParseChildMembers( uint32_t block_length = form_value.Unsigned(); uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); - if (DWARFExpression::Evaluate( - nullptr, nullptr, nullptr, nullptr, module_sp, - debug_info_data, die.GetCU(), block_offset, - block_length, eRegisterKindDWARF, &initialValue, - nullptr, memberOffset, nullptr)) { + if (DWARFExpression::Evaluate(nullptr, nullptr, module_sp, + debug_info_data, die.GetCU(), + block_offset, block_length, + eRegisterKindDWARF, &initialValue, + nullptr, memberOffset, nullptr)) { member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); } } else { diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp index 2507465750c7f..e04dc76d1dbe0 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp @@ -662,8 +662,6 @@ size_t DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc, form_value.BlockData() - debug_info_data.GetDataStart(); if (DWARFExpression::Evaluate( NULL, // ExecutionContext * - NULL, // ClangExpressionVariableList * - NULL, // ClangExpressionDeclMap * NULL, // RegisterContext * module_sp, debug_info_data, die.GetCU(), block_offset, block_length, eRegisterKindDWARF, &initialValue, NULL, diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp index 79b2acc4b4f38..5d7b12067263e 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -39,68 +39,48 @@ using namespace std; extern int g_verbose; DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF *dwarf2Data) - : m_dwarf2Data(dwarf2Data), m_abbrevs(NULL), m_user_data(NULL), - m_die_array(), m_func_aranges_ap(), m_base_addr(0), - m_offset(DW_INVALID_OFFSET), m_length(0), m_version(0), - m_addr_size(DWARFCompileUnit::GetDefaultAddressSize()), - m_producer(eProducerInvalid), m_producer_version_major(0), - m_producer_version_minor(0), m_producer_version_update(0), - m_language_type(eLanguageTypeUnknown), m_is_dwarf64(false), - m_is_optimized(eLazyBoolCalculate), m_addr_base(0), - m_ranges_base(0), m_base_obj_offset(DW_INVALID_OFFSET) {} + : m_dwarf2Data(dwarf2Data) {} DWARFCompileUnit::~DWARFCompileUnit() {} -void DWARFCompileUnit::Clear() { - m_offset = DW_INVALID_OFFSET; - m_length = 0; - m_version = 0; - m_abbrevs = NULL; - m_addr_size = DWARFCompileUnit::GetDefaultAddressSize(); - m_base_addr = 0; - m_die_array.clear(); - m_func_aranges_ap.reset(); - m_user_data = NULL; - m_producer = eProducerInvalid; - m_language_type = eLanguageTypeUnknown; - m_is_dwarf64 = false; - m_is_optimized = eLazyBoolCalculate; - m_addr_base = 0; - m_base_obj_offset = DW_INVALID_OFFSET; -} +DWARFCompileUnitSP DWARFCompileUnit::Extract(SymbolFileDWARF *dwarf2Data, + lldb::offset_t *offset_ptr) { + DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(dwarf2Data)); + // Out of memory? + if (cu_sp.get() == NULL) + return nullptr; -bool DWARFCompileUnit::Extract(const DWARFDataExtractor &debug_info, - lldb::offset_t *offset_ptr) { - Clear(); + const DWARFDataExtractor &debug_info = dwarf2Data->get_debug_info_data(); - m_offset = *offset_ptr; + cu_sp->m_offset = *offset_ptr; if (debug_info.ValidOffset(*offset_ptr)) { dw_offset_t abbr_offset; - const DWARFDebugAbbrev *abbr = m_dwarf2Data->DebugAbbrev(); - m_length = debug_info.GetDWARFInitialLength(offset_ptr); - m_is_dwarf64 = debug_info.IsDWARF64(); - m_version = debug_info.GetU16(offset_ptr); + const DWARFDebugAbbrev *abbr = dwarf2Data->DebugAbbrev(); + cu_sp->m_length = debug_info.GetDWARFInitialLength(offset_ptr); + cu_sp->m_is_dwarf64 = debug_info.IsDWARF64(); + cu_sp->m_version = debug_info.GetU16(offset_ptr); abbr_offset = debug_info.GetDWARFOffset(offset_ptr); - m_addr_size = debug_info.GetU8(offset_ptr); + cu_sp->m_addr_size = debug_info.GetU8(offset_ptr); - bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset() - 1); - bool version_OK = SymbolFileDWARF::SupportedVersion(m_version); + bool length_OK = + debug_info.ValidOffset(cu_sp->GetNextCompileUnitOffset() - 1); + bool version_OK = SymbolFileDWARF::SupportedVersion(cu_sp->m_version); bool abbr_offset_OK = - m_dwarf2Data->get_debug_abbrev_data().ValidOffset(abbr_offset); - bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8)); + dwarf2Data->get_debug_abbrev_data().ValidOffset(abbr_offset); + bool addr_size_OK = (cu_sp->m_addr_size == 4) || (cu_sp->m_addr_size == 8); if (length_OK && version_OK && addr_size_OK && abbr_offset_OK && abbr != NULL) { - m_abbrevs = abbr->GetAbbreviationDeclarationSet(abbr_offset); - return true; + cu_sp->m_abbrevs = abbr->GetAbbreviationDeclarationSet(abbr_offset); + return cu_sp; } // reset the offset to where we tried to parse from if anything went wrong - *offset_ptr = m_offset; + *offset_ptr = cu_sp->m_offset; } - return false; + return nullptr; } void DWARFCompileUnit::ClearDIEs(bool keep_compile_unit_die) { @@ -620,6 +600,10 @@ void DWARFCompileUnit::Index(NameToDIE &func_basenames, NameToDIE &objc_class_selectors, NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces) { + assert(!m_dwarf2Data->GetBaseCompileUnit() && + "DWARFCompileUnit associated with .dwo or .dwp " + "should not be indexed directly"); + Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); if (log) { diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h index 430251337575a..8ea0d6465adf4 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h @@ -18,6 +18,8 @@ class NameToDIE; class SymbolFileDWARF; class SymbolFileDWARFDwo; +typedef std::shared_ptr<DWARFCompileUnit> DWARFCompileUnitSP; + class DWARFCompileUnit { public: enum Producer { @@ -28,39 +30,35 @@ public: eProcucerOther }; - DWARFCompileUnit(SymbolFileDWARF *dwarf2Data); + static DWARFCompileUnitSP Extract(SymbolFileDWARF *dwarf2Data, + lldb::offset_t *offset_ptr); ~DWARFCompileUnit(); - bool Extract(const lldb_private::DWARFDataExtractor &debug_info, - lldb::offset_t *offset_ptr); size_t ExtractDIEsIfNeeded(bool cu_die_only); DWARFDIE LookupAddress(const dw_addr_t address); size_t AppendDIEsWithTag(const dw_tag_t tag, DWARFDIECollection &matching_dies, uint32_t depth = UINT32_MAX) const; - void Clear(); bool Verify(lldb_private::Stream *s) const; void Dump(lldb_private::Stream *s) const; + // Offset of the initial length field. dw_offset_t GetOffset() const { return m_offset; } lldb::user_id_t GetID() const; - uint32_t Size() const { - return m_is_dwarf64 ? 23 - : 11; /* Size in bytes of the compile unit header */ - } + // Size in bytes of the initial length + compile unit header. + uint32_t Size() const { return m_is_dwarf64 ? 23 : 11; } bool ContainsDIEOffset(dw_offset_t die_offset) const { return die_offset >= GetFirstDIEOffset() && die_offset < GetNextCompileUnitOffset(); } dw_offset_t GetFirstDIEOffset() const { return m_offset + Size(); } dw_offset_t GetNextCompileUnitOffset() const { - return m_offset + m_length + (m_is_dwarf64 ? 12 : 4); + return m_offset + (m_is_dwarf64 ? 12 : 4) + m_length; } + // Size of the CU data (without initial length and without header). size_t GetDebugInfoSize() const { - return m_length + (m_is_dwarf64 ? 12 : 4) - Size(); /* Size in bytes of the - .debug_info data - associated with this - compile unit. */ + return (m_is_dwarf64 ? 12 : 4) + m_length - Size(); } + // Size of the CU data incl. header but without initial length. uint32_t GetLength() const { return m_length; } uint16_t GetVersion() const { return m_version; } const DWARFAbbreviationDeclarationSet *GetAbbreviations() const { @@ -165,7 +163,7 @@ protected: SymbolFileDWARF *m_dwarf2Data; std::unique_ptr<SymbolFileDWARFDwo> m_dwo_symbol_file; const DWARFAbbreviationDeclarationSet *m_abbrevs; - void *m_user_data; + void *m_user_data = nullptr; DWARFDebugInfoEntry::collection m_die_array; // The compile unit debug information entry item std::unique_ptr<DWARFDebugAranges> m_func_aranges_ap; // A table similar to @@ -174,23 +172,24 @@ protected: // points to the exact // DW_TAG_subprogram // DIEs - dw_addr_t m_base_addr; + dw_addr_t m_base_addr = 0; + // Offset of the initial length field. dw_offset_t m_offset; dw_offset_t m_length; uint16_t m_version; uint8_t m_addr_size; - Producer m_producer; - uint32_t m_producer_version_major; - uint32_t m_producer_version_minor; - uint32_t m_producer_version_update; - lldb::LanguageType m_language_type; + Producer m_producer = eProducerInvalid; + uint32_t m_producer_version_major = 0; + uint32_t m_producer_version_minor = 0; + uint32_t m_producer_version_update = 0; + lldb::LanguageType m_language_type = lldb::eLanguageTypeUnknown; bool m_is_dwarf64; - lldb_private::LazyBool m_is_optimized; - dw_addr_t m_addr_base; // Value of DW_AT_addr_base - dw_addr_t m_ranges_base; // Value of DW_AT_ranges_base - dw_offset_t m_base_obj_offset; // If this is a dwo compile unit this is the - // offset of the base compile unit in the main - // object file + lldb_private::LazyBool m_is_optimized = lldb_private::eLazyBoolCalculate; + dw_addr_t m_addr_base = 0; // Value of DW_AT_addr_base + dw_addr_t m_ranges_base = 0; // Value of DW_AT_ranges_base + // If this is a dwo compile unit this is the offset of the base compile unit + // in the main object file + dw_offset_t m_base_obj_offset = DW_INVALID_OFFSET; void ParseProducerInfo(); @@ -203,6 +202,8 @@ protected: NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces); private: + DWARFCompileUnit(SymbolFileDWARF *dwarf2Data); + const DWARFDebugInfoEntry *GetCompileUnitDIEPtrOnly() { ExtractDIEsIfNeeded(true); if (m_die_array.empty()) diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index 5222419d3233e..4ef2e772ea5d3 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -392,17 +392,11 @@ lldb::ModuleSP DWARFDIE::GetContainingDWOModule() const { } bool DWARFDIE::HasChildren() const { - if (m_die) - return m_die->HasChildren(); - else - return false; + return m_die && m_die->HasChildren(); } bool DWARFDIE::Supports_DW_AT_APPLE_objc_complete_type() const { - if (IsValid()) - return GetDWARF()->Supports_DW_AT_APPLE_objc_complete_type(m_cu); - else - return false; + return IsValid() && GetDWARF()->Supports_DW_AT_APPLE_objc_complete_type(m_cu); } size_t DWARFDIE::GetAttributes(DWARFAttributes &attributes, @@ -464,5 +458,5 @@ bool operator==(const DWARFDIE &lhs, const DWARFDIE &rhs) { } bool operator!=(const DWARFDIE &lhs, const DWARFDIE &rhs) { - return lhs.GetDIE() != rhs.GetDIE() || lhs.GetCU() != rhs.GetCU(); + return !(lhs == rhs); } diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp index d681925daeacc..1cf0e7eeeb600 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp @@ -98,6 +98,21 @@ dw_uleb128_t DWARFAbbreviationDeclarationSet::AppendAbbrevDeclSequential( } //---------------------------------------------------------------------- +// DWARFAbbreviationDeclarationSet::GetUnsupportedForms() +//---------------------------------------------------------------------- +void DWARFAbbreviationDeclarationSet::GetUnsupportedForms( + std::set<dw_form_t> &invalid_forms) const { + for (const auto &abbr_decl : m_decls) { + const size_t num_attrs = abbr_decl.NumAttributes(); + for (size_t i=0; i<num_attrs; ++i) { + dw_form_t form = abbr_decl.GetFormByIndex(i); + if (!DWARFFormValue::FormIsSupported(form)) + invalid_forms.insert(form); + } + } +} + +//---------------------------------------------------------------------- // Encode // // Encode the abbreviation table onto the end of the buffer provided @@ -175,3 +190,12 @@ DWARFDebugAbbrev::GetAbbreviationDeclarationSet( return &(pos->second); return NULL; } + +//---------------------------------------------------------------------- +// DWARFDebugAbbrev::GetUnsupportedForms() +//---------------------------------------------------------------------- +void DWARFDebugAbbrev::GetUnsupportedForms( + std::set<dw_form_t> &invalid_forms) const { + for (const auto &pair : m_abbrevCollMap) + pair.second.GetUnsupportedForms(invalid_forms); +} diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h index 137c81780513c..2bacb6349b6fc 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h @@ -41,6 +41,7 @@ public: // void Encode(BinaryStreamBuf& debug_abbrev_buf) const; dw_uleb128_t AppendAbbrevDeclSequential(const DWARFAbbreviationDeclaration &abbrevDecl); + void GetUnsupportedForms(std::set<dw_form_t> &invalid_forms) const; const DWARFAbbreviationDeclaration * GetAbbreviationDeclaration(dw_uleb128_t abbrCode) const; @@ -65,6 +66,7 @@ public: GetAbbreviationDeclarationSet(dw_offset_t cu_abbr_offset) const; void Dump(lldb_private::Stream *s) const; void Parse(const lldb_private::DWARFDataExtractor &data); + void GetUnsupportedForms(std::set<dw_form_t> &invalid_forms) const; protected: DWARFAbbreviationDeclarationCollMap m_abbrevCollMap; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp index eff9850d435dd..9c0f1d3c89056 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -97,17 +97,8 @@ void DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded() { if (m_compile_units.empty()) { if (m_dwarf2Data != NULL) { lldb::offset_t offset = 0; - const DWARFDataExtractor &debug_info_data = - m_dwarf2Data->get_debug_info_data(); - while (debug_info_data.ValidOffset(offset)) { - DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(m_dwarf2Data)); - // Out of memory? - if (cu_sp.get() == NULL) - break; - - if (cu_sp->Extract(debug_info_data, &offset) == false) - break; - + DWARFCompileUnitSP cu_sp; + while ((cu_sp = DWARFCompileUnit::Extract(m_dwarf2Data, &offset))) { m_compile_units.push_back(cu_sp); offset = cu_sp->GetNextCompileUnitOffset(); @@ -248,12 +239,10 @@ void DWARFDebugInfo::Parse(SymbolFileDWARF *dwarf2Data, Callback callback, if (dwarf2Data) { lldb::offset_t offset = 0; uint32_t depth = 0; - DWARFCompileUnitSP cu(new DWARFCompileUnit(dwarf2Data)); - if (cu.get() == NULL) - return; DWARFDebugInfoEntry die; - while (cu->Extract(dwarf2Data->get_debug_info_data(), &offset)) { + DWARFCompileUnitSP cu; + while ((cu = DWARFCompileUnit::Extract(dwarf2Data, &offset))) { const dw_offset_t next_cu_offset = cu->GetNextCompileUnitOffset(); depth = 0; @@ -288,12 +277,6 @@ void DWARFDebugInfo::Parse(SymbolFileDWARF *dwarf2Data, Callback callback, if (!dwarf2Data->get_debug_info_data().ValidOffset(offset)) break; - // See if during the callback anyone retained a copy of the compile - // unit other than ourselves and if so, let whomever did own the object - // and create a new one for our own use! - if (!cu.unique()) - cu.reset(new DWARFCompileUnit(dwarf2Data)); - // Make sure we start on a proper offset = next_cu_offset; } @@ -507,80 +490,3 @@ void DWARFDebugInfo::Dump(Stream *s, const uint32_t die_offset, die.Dump(s, recurse_depth); } } - -//---------------------------------------------------------------------- -// FindCallbackString -// -// A callback function for the static DWARFDebugInfo::Parse() function -// that gets called each time a compile unit header or debug information -// entry is successfully parsed. -// -// This function will find the die_offset of any items whose DW_AT_name -// matches the given string -//---------------------------------------------------------------------- -typedef struct FindCallbackStringInfoTag { - const char *name; - bool ignore_case; - RegularExpression *regex; - vector<dw_offset_t> &die_offsets; -} FindCallbackStringInfo; - -static dw_offset_t -FindCallbackString(SymbolFileDWARF *dwarf2Data, DWARFCompileUnit *cu, - DWARFDebugInfoEntry *die, const dw_offset_t next_offset, - const uint32_t curr_depth, void *userData) { - FindCallbackStringInfo *info = (FindCallbackStringInfo *)userData; - - if (!die) - return next_offset; - - const char *die_name = die->GetName(dwarf2Data, cu); - if (!die_name) - return next_offset; - - if (info->regex) { - if (info->regex->Execute(llvm::StringRef(die_name))) - info->die_offsets.push_back(die->GetOffset()); - } else { - if ((info->ignore_case ? strcasecmp(die_name, info->name) - : strcmp(die_name, info->name)) == 0) - info->die_offsets.push_back(die->GetOffset()); - } - - // Just return the current offset to parse the next CU or DIE entry - return next_offset; -} - -//---------------------------------------------------------------------- -// Find -// -// Finds all DIE that have a specific DW_AT_name attribute by manually -// searching through the debug information (not using the -// .debug_pubnames section). The string must match the entire name -// and case sensitive searches are an option. -//---------------------------------------------------------------------- -bool DWARFDebugInfo::Find(const char *name, bool ignore_case, - vector<dw_offset_t> &die_offsets) const { - die_offsets.clear(); - if (name && name[0]) { - FindCallbackStringInfo info = {name, ignore_case, NULL, die_offsets}; - DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info); - } - return !die_offsets.empty(); -} - -//---------------------------------------------------------------------- -// Find -// -// Finds all DIE that have a specific DW_AT_name attribute by manually -// searching through the debug information (not using the -// .debug_pubnames section). The string must match the supplied regular -// expression. -//---------------------------------------------------------------------- -bool DWARFDebugInfo::Find(RegularExpression &re, - vector<dw_offset_t> &die_offsets) const { - die_offsets.clear(); - FindCallbackStringInfo info = {NULL, false, &re, die_offsets}; - DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info); - return !die_offsets.empty(); -} diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h index be4e18b12be0b..14c7d767d05b4 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h @@ -50,10 +50,6 @@ public: static void Verify(lldb_private::Stream *s, SymbolFileDWARF *dwarf2Data); static void Dump(lldb_private::Stream *s, SymbolFileDWARF *dwarf2Data, const uint32_t die_offset, const uint32_t recurse_depth); - bool Find(const char *name, bool ignore_case, - std::vector<dw_offset_t> &die_offsets) const; - bool Find(lldb_private::RegularExpression &re, - std::vector<dw_offset_t> &die_offsets) const; enum { eDumpFlag_Verbose = (1 << 0), // Verbose dumping @@ -65,8 +61,6 @@ public: DWARFDebugAranges &GetCompileUnitAranges(); protected: - typedef std::shared_ptr<DWARFCompileUnit> DWARFCompileUnitSP; - static bool OffsetLessThanCompileUnitOffset(dw_offset_t offset, const DWARFCompileUnitSP &cu_sp); diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 8d87c201eceb2..f595bd83d8469 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -161,9 +161,9 @@ bool DWARFDebugInfoEntry::FastExtract( case DW_FORM_strp: case DW_FORM_sec_offset: if (cu->IsDWARF64()) - debug_info_data.GetU64(offset_ptr); + debug_info_data.GetU64(&offset); else - debug_info_data.GetU32(offset_ptr); + debug_info_data.GetU32(&offset); break; default: @@ -325,9 +325,9 @@ bool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data, case DW_FORM_strp: case DW_FORM_sec_offset: if (cu->IsDWARF64()) - debug_info_data.GetU64(offset_ptr); + debug_info_data.GetU64(&offset); else - debug_info_data.GetU32(offset_ptr); + debug_info_data.GetU32(&offset); break; default: @@ -1314,19 +1314,6 @@ bool DWARFDebugInfoEntry::AppendTypeName(SymbolFileDWARF *dwarf2Data, return false; } -bool DWARFDebugInfoEntry::Contains(const DWARFDebugInfoEntry *die) const { - if (die) { - const dw_offset_t die_offset = die->GetOffset(); - if (die_offset > GetOffset()) { - const DWARFDebugInfoEntry *sibling = GetSibling(); - assert(sibling); // TODO: take this out - if (sibling) - return die_offset < sibling->GetOffset(); - } - } - return false; -} - //---------------------------------------------------------------------- // BuildAddressRangeTable //---------------------------------------------------------------------- diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index 15abac77a475d..89450d327adfd 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -60,18 +60,6 @@ public: m_empty_children(false), m_abbr_idx(0), m_has_children(false), m_tag(0) {} - void Clear() { - m_offset = DW_INVALID_OFFSET; - m_parent_idx = 0; - m_sibling_idx = 0; - m_empty_children = false; - m_abbr_idx = 0; - m_has_children = false; - m_tag = 0; - } - - bool Contains(const DWARFDebugInfoEntry *die) const; - void BuildAddressRangeTable(SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, DWARFDebugAranges *debug_aranges) const; @@ -211,8 +199,6 @@ public: dw_offset_t GetOffset() const { return m_offset; } - void SetOffset(dw_offset_t offset) { m_offset = offset; } - bool HasChildren() const { return m_has_children; } void SetHasChildren(bool b) { m_has_children = b; } diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp index 515c083fedb08..a8c48b7f2f849 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp @@ -15,6 +15,18 @@ using namespace lldb_private; using namespace std; +static dw_addr_t GetBaseAddressMarker(uint32_t addr_size) { + switch(addr_size) { + case 2: + return 0xffff; + case 4: + return 0xffffffff; + case 8: + return 0xffffffffffffffff; + } + llvm_unreachable("GetBaseAddressMarker unsupported address size."); +} + DWARFDebugRanges::DWARFDebugRanges() : m_range_map() {} DWARFDebugRanges::~DWARFDebugRanges() {} @@ -39,38 +51,27 @@ bool DWARFDebugRanges::Extract(SymbolFileDWARF *dwarf2Data, const DWARFDataExtractor &debug_ranges_data = dwarf2Data->get_debug_ranges_data(); uint32_t addr_size = debug_ranges_data.GetAddressByteSize(); + dw_addr_t base_addr = 0; + dw_addr_t base_addr_marker = GetBaseAddressMarker(addr_size); while ( debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) { dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); + if (!begin && !end) { // End of range list break; } - // Extend 4 byte addresses that consists of 32 bits of 1's to be 64 bits - // of ones - switch (addr_size) { - case 2: - if (begin == 0xFFFFull) - begin = LLDB_INVALID_ADDRESS; - break; - - case 4: - if (begin == 0xFFFFFFFFull) - begin = LLDB_INVALID_ADDRESS; - break; - case 8: - break; - - default: - llvm_unreachable("DWARFRangeList::Extract() unsupported address size."); + if (begin == base_addr_marker) { + base_addr = end; + continue; } // Filter out empty ranges if (begin < end) - range_list.Append(DWARFRangeList::Entry(begin, end - begin)); + range_list.Append(DWARFRangeList::Entry(begin + base_addr, end - begin)); } // Make sure we consumed at least something diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp index 0853671ee8749..a21e313c2f811 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -725,3 +725,39 @@ int DWARFFormValue::Compare(const DWARFFormValue &a_value, } return -1; } + +bool DWARFFormValue::FormIsSupported(dw_form_t form) { + switch (form) { + case DW_FORM_addr: + case DW_FORM_block2: + case DW_FORM_block4: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + case DW_FORM_string: + case DW_FORM_block: + case DW_FORM_block1: + case DW_FORM_data1: + case DW_FORM_flag: + case DW_FORM_sdata: + case DW_FORM_strp: + case DW_FORM_udata: + case DW_FORM_ref_addr: + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref8: + case DW_FORM_ref_udata: + case DW_FORM_indirect: + case DW_FORM_sec_offset: + case DW_FORM_exprloc: + case DW_FORM_flag_present: + case DW_FORM_ref_sig8: + case DW_FORM_GNU_str_index: + case DW_FORM_GNU_addr_index: + return true; + default: + break; + } + return false; +} diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h index 8d6af3d65b331..2aa7460c49109 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h @@ -86,6 +86,7 @@ public: bool is_dwarf64); static int Compare(const DWARFFormValue &a, const DWARFFormValue &b); void Clear(); + static bool FormIsSupported(dw_form_t form); protected: const DWARFCompileUnit *m_cu; // Compile unit for this form diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index ef18c2b5d3bab..f149ec354f08c 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -13,7 +13,6 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Threading.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" @@ -22,6 +21,7 @@ #include "lldb/Core/Section.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/Value.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" @@ -30,6 +30,7 @@ #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" +#include "lldb/Host/Symbols.h" #include "lldb/Interpreter/OptionValueFileSpecList.h" #include "lldb/Interpreter/OptionValueProperties.h" @@ -53,7 +54,7 @@ #include "lldb/Target/Language.h" -#include "lldb/Utility/TaskPool.h" +#include "lldb/Host/TaskPool.h" #include "DWARFASTParser.h" #include "DWARFASTParserClang.h" @@ -71,6 +72,7 @@ #include "LogChannelDWARF.h" #include "SymbolFileDWARFDebugMap.h" #include "SymbolFileDWARFDwo.h" +#include "SymbolFileDWARFDwp.h" #include "llvm/Support/FileSystem.h" @@ -207,6 +209,10 @@ static const char *resolveCompDir(const char *path_from_dwarf) { return nullptr; } +DWARFCompileUnit *SymbolFileDWARF::GetBaseCompileUnit() { + return nullptr; +} + void SymbolFileDWARF::Initialize() { LogChannelDWARF::Initialize(); PluginManager::RegisterPlugin(GetPluginNameStatic(), @@ -435,13 +441,11 @@ void SymbolFileDWARF::InitializeObject() { ModuleSP module_sp(m_obj_file->GetModule()); if (module_sp) { const SectionList *section_list = module_sp->GetSectionList(); - const Section *section = + Section *section = section_list->FindSectionByName(GetDWARFMachOSegmentName()).get(); - // Memory map the DWARF mach-o segment so we have everything mmap'ed - // to keep our heap memory usage down. if (section) - m_obj_file->MemoryMapSectionData(section, m_dwarf_data); + m_obj_file->ReadSectionData(section, m_dwarf_data); } get_apple_names_data(); @@ -497,6 +501,21 @@ uint32_t SymbolFileDWARF::CalculateAbilities() { if (section_list == NULL) return 0; + // On non Apple platforms we might have .debug_types debug info that + // is created by using "-fdebug-types-section". LLDB currently will try + // to load this debug info, but it causes crashes during debugging when + // types are missing since it doesn't know how to parse the info in + // the .debug_types type units. This causes all complex debug info + // types to be unresolved. Because this causes LLDB to crash and since + // it really doesn't provide a solid debuggiung experience, we should + // disable trying to debug this kind of DWARF until support gets + // added or deprecated. + if (section_list->FindSectionByName(ConstString(".debug_types"))) { + m_obj_file->GetModule()->ReportWarning( + "lldb doesn’t support .debug_types debug info"); + return 0; + } + uint64_t debug_abbrev_file_size = 0; uint64_t debug_info_file_size = 0; uint64_t debug_line_file_size = 0; @@ -517,6 +536,20 @@ uint32_t SymbolFileDWARF::CalculateAbilities() { if (section) debug_abbrev_file_size = section->GetFileSize(); + DWARFDebugAbbrev *abbrev = DebugAbbrev(); + if (abbrev) { + std::set<dw_form_t> invalid_forms; + abbrev->GetUnsupportedForms(invalid_forms); + if (!invalid_forms.empty()) { + StreamString error; + error.Printf("unsupported DW_FORM value%s:", invalid_forms.size() > 1 ? "s" : ""); + for (auto form : invalid_forms) + error.Printf(" %#x", form); + m_obj_file->GetModule()->ReportWarning("%s", error.GetString().str().c_str()); + return 0; + } + } + section = section_list->FindSectionByType(eSectionTypeDWARFDebugLine, true) .get(); @@ -1539,6 +1572,16 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( if (!dwo_name) return nullptr; + SymbolFileDWARFDwp *dwp_symfile = GetDwpSymbolFile(); + if (dwp_symfile) { + uint64_t dwo_id = cu_die.GetAttributeValueAsUnsigned(this, &dwarf_cu, + DW_AT_GNU_dwo_id, 0); + std::unique_ptr<SymbolFileDWARFDwo> dwo_symfile = + dwp_symfile->GetSymbolFileForDwoId(&dwarf_cu, dwo_id); + if (dwo_symfile) + return dwo_symfile; + } + FileSpec dwo_file(dwo_name, true); if (dwo_file.IsRelative()) { const char *comp_dir = cu_die.GetAttributeValueAsString( @@ -1600,7 +1643,29 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { } dwo_module_spec.GetArchitecture() = m_obj_file->GetModule()->GetArchitecture(); - // printf ("Loading dwo = '%s'\n", dwo_path); + + // When LLDB loads "external" modules it looks at the + // presence of DW_AT_GNU_dwo_name. + // However, when the already created module + // (corresponding to .dwo itself) is being processed, + // it will see the presence of DW_AT_GNU_dwo_name + // (which contains the name of dwo file) and + // will try to call ModuleList::GetSharedModule again. + // In some cases (i.e. for empty files) Clang 4.0 + // generates a *.dwo file which has DW_AT_GNU_dwo_name, + // but no DW_AT_comp_dir. In this case the method + // ModuleList::GetSharedModule will fail and + // the warning will be printed. However, as one can notice + // in this case we don't actually need to try to load the already + // loaded module (corresponding to .dwo) so we simply skip it. + if (m_obj_file->GetFileSpec() + .GetFileNameExtension() + .GetStringRef() == "dwo" && + llvm::StringRef(m_obj_file->GetFileSpec().GetPath()) + .endswith(dwo_module_spec.GetFileSpec().GetPath())) { + continue; + } + Status error = ModuleList::GetSharedModule( dwo_module_spec, module_sp, NULL, NULL, NULL); if (!module_sp) { @@ -1640,9 +1705,8 @@ SymbolFileDWARF::GlobalVariableMap &SymbolFileDWARF::GetGlobalAranges() { const DWARFExpression &location = var_sp->LocationExpression(); Value location_result; Status error; - if (location.Evaluate(nullptr, nullptr, nullptr, - LLDB_INVALID_ADDRESS, nullptr, nullptr, - location_result, &error)) { + if (location.Evaluate(nullptr, LLDB_INVALID_ADDRESS, nullptr, + nullptr, location_result, &error)) { if (location_result.GetValueType() == Value::eValueTypeFileAddress) { lldb::addr_t file_addr = @@ -4288,3 +4352,18 @@ DWARFExpression::LocationListFormat SymbolFileDWARF::GetLocationListFormat() const { return DWARFExpression::RegularLocationList; } + +SymbolFileDWARFDwp *SymbolFileDWARF::GetDwpSymbolFile() { + llvm::call_once(m_dwp_symfile_once_flag, [this]() { + ModuleSpec module_spec; + module_spec.GetFileSpec() = m_obj_file->GetFileSpec(); + module_spec.GetSymbolFileSpec() = + FileSpec(m_obj_file->GetFileSpec().GetPath() + ".dwp", false); + FileSpec dwp_filespec = Symbols::LocateExecutableSymbolFile(module_spec); + if (dwp_filespec.Exists()) { + m_dwp_symfile = SymbolFileDWARFDwp::Create(GetObjectFile()->GetModule(), + dwp_filespec); + } + }); + return m_dwp_symfile.get(); +} diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 9b1eb1d76fea9..6902dc0333d2f 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -61,6 +61,7 @@ class DWARFDIECollection; class DWARFFormValue; class SymbolFileDWARFDebugMap; class SymbolFileDWARFDwo; +class SymbolFileDWARFDwp; #define DIE_IS_BEING_PARSED ((lldb_private::Type *)1) @@ -275,8 +276,8 @@ public: GetCompUnitForDWARFCompUnit(DWARFCompileUnit *dwarf_cu, uint32_t cu_idx = UINT32_MAX); - size_t GetObjCMethodDIEOffsets(lldb_private::ConstString class_name, - DIEArray &method_die_offsets); + virtual size_t GetObjCMethodDIEOffsets(lldb_private::ConstString class_name, + DIEArray &method_die_offsets); bool Supports_DW_AT_APPLE_objc_complete_type(DWARFCompileUnit *cu); @@ -298,6 +299,11 @@ public: GetDwoSymbolFileForCompileUnit(DWARFCompileUnit &dwarf_cu, const DWARFDebugInfoEntry &cu_die); + // For regular SymbolFileDWARF instances the method returns nullptr, + // for the instances of the subclass SymbolFileDWARFDwo + // the method returns a pointer to the base compile unit. + virtual DWARFCompileUnit *GetBaseCompileUnit(); + protected: typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr; @@ -391,14 +397,10 @@ protected: virtual lldb::TypeSP FindDefinitionTypeForDWARFDeclContext(const DWARFDeclContext &die_decl_ctx); - lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE( + virtual lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE( const DWARFDIE &die, const lldb_private::ConstString &type_name, bool must_be_implementation); - lldb::TypeSP - FindCompleteObjCDefinitionType(const lldb_private::ConstString &type_name, - bool header_definition_ok); - lldb_private::Symbol * GetObjCClassSymbol(const lldb_private::ConstString &objc_class_name); @@ -464,8 +466,14 @@ protected: return m_forward_decl_clang_type_to_die; } + SymbolFileDWARFDwp *GetDwpSymbolFile(); + lldb::ModuleWP m_debug_map_module_wp; SymbolFileDWARFDebugMap *m_debug_map_symfile; + + llvm::once_flag m_dwp_symfile_once_flag; + std::unique_ptr<SymbolFileDWARFDwp> m_dwp_symfile; + lldb_private::DWARFDataExtractor m_dwarf_data; DWARFDataSegment m_data_debug_abbrev; diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp index c14ebd1628be6..17c188a41a773 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp @@ -61,6 +61,14 @@ SymbolFileDWARFDwo::ParseCompileUnit(DWARFCompileUnit *dwarf_cu, } DWARFCompileUnit *SymbolFileDWARFDwo::GetCompileUnit() { + // A clang module is found via a skeleton CU, but is not a proper DWO. + // Clang modules have a .debug_info section instead of the *_dwo variant. + if (auto *section_list = m_obj_file->GetSectionList(false)) + if (auto section_sp = + section_list->FindSectionByType(eSectionTypeDWARFDebugInfo, true)) + if (!section_sp->GetName().GetStringRef().endswith("dwo")) + return nullptr; + // Only dwo files with 1 compile unit is supported if (GetNumCompileUnits() == 1) return DebugInfo()->GetCompileUnitAtIndex(0); @@ -91,6 +99,12 @@ SymbolFileDWARFDwo::GetForwardDeclClangTypeToDie() { return GetBaseSymbolFile()->GetForwardDeclClangTypeToDie(); } +size_t SymbolFileDWARFDwo::GetObjCMethodDIEOffsets( + lldb_private::ConstString class_name, DIEArray &method_die_offsets) { + return GetBaseSymbolFile()->GetObjCMethodDIEOffsets( + class_name, method_die_offsets); +} + UniqueDWARFASTTypeMap &SymbolFileDWARFDwo::GetUniqueDWARFASTTypeMap() { return GetBaseSymbolFile()->GetUniqueDWARFASTTypeMap(); } @@ -101,6 +115,17 @@ lldb::TypeSP SymbolFileDWARFDwo::FindDefinitionTypeForDWARFDeclContext( die_decl_ctx); } +lldb::TypeSP SymbolFileDWARFDwo::FindCompleteObjCDefinitionTypeForDIE( + const DWARFDIE &die, const lldb_private::ConstString &type_name, + bool must_be_implementation) { + return GetBaseSymbolFile()->FindCompleteObjCDefinitionTypeForDIE( + die, type_name, must_be_implementation); +} + +DWARFCompileUnit *SymbolFileDWARFDwo::GetBaseCompileUnit() { + return m_base_dwarf_cu; +} + SymbolFileDWARF *SymbolFileDWARFDwo::GetBaseSymbolFile() { return m_base_dwarf_cu->GetSymbolFileDWARF(); } diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h index 8cd67a2b24247..b67967aafab26 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h @@ -33,6 +33,9 @@ public: lldb_private::DWARFExpression::LocationListFormat GetLocationListFormat() const override; + size_t GetObjCMethodDIEOffsets(lldb_private::ConstString class_name, + DIEArray &method_die_offsets) override; + lldb_private::TypeSystem * GetTypeSystemForLanguage(lldb::LanguageType language) override; @@ -45,6 +48,8 @@ public: return nullptr; } + DWARFCompileUnit *GetBaseCompileUnit() override; + protected: void LoadSectionData(lldb::SectionType sect_type, lldb_private::DWARFDataExtractor &data) override; @@ -62,6 +67,10 @@ protected: lldb::TypeSP FindDefinitionTypeForDWARFDeclContext( const DWARFDeclContext &die_decl_ctx) override; + lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE( + const DWARFDIE &die, const lldb_private::ConstString &type_name, + bool must_be_implementation) override; + SymbolFileDWARF *GetBaseSymbolFile(); lldb::ObjectFileSP m_obj_file_sp; diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp new file mode 100644 index 0000000000000..f6de1818eae08 --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp @@ -0,0 +1,36 @@ +//===-- SymbolFileDWARFDwoDwp.cpp -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "SymbolFileDWARFDwoDwp.h" + +#include "lldb/Core/Section.h" +#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Utility/LLDBAssert.h" + +#include "DWARFCompileUnit.h" +#include "DWARFDebugInfo.h" + +using namespace lldb; +using namespace lldb_private; + +SymbolFileDWARFDwoDwp::SymbolFileDWARFDwoDwp(SymbolFileDWARFDwp *dwp_symfile, + ObjectFileSP objfile, + DWARFCompileUnit *dwarf_cu, + uint64_t dwo_id) + : SymbolFileDWARFDwo(objfile, dwarf_cu), m_dwp_symfile(dwp_symfile), + m_dwo_id(dwo_id) {} + +void SymbolFileDWARFDwoDwp::LoadSectionData(lldb::SectionType sect_type, + DWARFDataExtractor &data) { + if (m_dwp_symfile->LoadSectionData(m_dwo_id, sect_type, data)) + return; + + SymbolFileDWARF::LoadSectionData(sect_type, data); +} diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h new file mode 100644 index 0000000000000..00ad7aafd96b0 --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h @@ -0,0 +1,34 @@ +//===-- SymbolFileDWARFDwoDwp.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARFDwoDwp_SymbolFileDWARFDwoDwp_h_ +#define SymbolFileDWARFDwoDwp_SymbolFileDWARFDwoDwp_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "SymbolFileDWARFDwo.h" +#include "SymbolFileDWARFDwp.h" + +class SymbolFileDWARFDwoDwp : public SymbolFileDWARFDwo { +public: + SymbolFileDWARFDwoDwp(SymbolFileDWARFDwp *dwp_symfile, + lldb::ObjectFileSP objfile, DWARFCompileUnit *dwarf_cu, + uint64_t dwo_id); + +protected: + void LoadSectionData(lldb::SectionType sect_type, + lldb_private::DWARFDataExtractor &data) override; + + SymbolFileDWARFDwp *m_dwp_symfile; + uint64_t m_dwo_id; +}; + +#endif // SymbolFileDWARFDwoDwp_SymbolFileDWARFDwoDwp_h_ diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp new file mode 100644 index 0000000000000..1dc1dab34a5c4 --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp @@ -0,0 +1,142 @@ +//===-- SymbolFileDWARFDwp.cpp ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "SymbolFileDWARFDwp.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Section.h" +#include "lldb/Symbol/ObjectFile.h" + +#include "SymbolFileDWARFDwoDwp.h" + +static llvm::DWARFSectionKind +lldbSectTypeToLlvmSectionKind(lldb::SectionType type) { + switch (type) { + case lldb::eSectionTypeDWARFDebugInfo: + return llvm::DW_SECT_INFO; + // case lldb::eSectionTypeDWARFDebugTypes: + // return llvm::DW_SECT_TYPES; + case lldb::eSectionTypeDWARFDebugAbbrev: + return llvm::DW_SECT_ABBREV; + case lldb::eSectionTypeDWARFDebugLine: + return llvm::DW_SECT_LINE; + case lldb::eSectionTypeDWARFDebugLoc: + return llvm::DW_SECT_LOC; + case lldb::eSectionTypeDWARFDebugStrOffsets: + return llvm::DW_SECT_STR_OFFSETS; + // case lldb::eSectionTypeDWARFDebugMacinfo: + // return llvm::DW_SECT_MACINFO; + case lldb::eSectionTypeDWARFDebugMacro: + return llvm::DW_SECT_MACRO; + default: + // Note: 0 is an invalid dwarf section kind. + return llvm::DWARFSectionKind(0); + } +} + +std::unique_ptr<SymbolFileDWARFDwp> +SymbolFileDWARFDwp::Create(lldb::ModuleSP module_sp, + const lldb_private::FileSpec &file_spec) { + const lldb::offset_t file_offset = 0; + lldb::DataBufferSP file_data_sp; + lldb::offset_t file_data_offset = 0; + lldb::ObjectFileSP obj_file = lldb_private::ObjectFile::FindPlugin( + module_sp, &file_spec, file_offset, file_spec.GetByteSize(), file_data_sp, + file_data_offset); + if (obj_file == nullptr) + return nullptr; + + std::unique_ptr<SymbolFileDWARFDwp> dwp_symfile( + new SymbolFileDWARFDwp(module_sp, obj_file)); + + lldb_private::DWARFDataExtractor debug_cu_index; + if (!dwp_symfile->LoadRawSectionData(lldb::eSectionTypeDWARFDebugCuIndex, + debug_cu_index)) + return nullptr; + + llvm::DataExtractor llvm_debug_cu_index( + llvm::StringRef(debug_cu_index.PeekCStr(0), debug_cu_index.GetByteSize()), + debug_cu_index.GetByteOrder() == lldb::eByteOrderLittle, + debug_cu_index.GetAddressByteSize()); + if (!dwp_symfile->m_debug_cu_index.parse(llvm_debug_cu_index)) + return nullptr; + dwp_symfile->InitDebugCUIndexMap(); + return dwp_symfile; +} + +void SymbolFileDWARFDwp::InitDebugCUIndexMap() { + m_debug_cu_index_map.clear(); + for (const auto &entry : m_debug_cu_index.getRows()) + m_debug_cu_index_map.emplace(entry.getSignature(), &entry); +} + +SymbolFileDWARFDwp::SymbolFileDWARFDwp(lldb::ModuleSP module_sp, + lldb::ObjectFileSP obj_file) + : m_obj_file(std::move(obj_file)), m_debug_cu_index(llvm::DW_SECT_INFO) +{} + +std::unique_ptr<SymbolFileDWARFDwo> +SymbolFileDWARFDwp::GetSymbolFileForDwoId(DWARFCompileUnit *dwarf_cu, + uint64_t dwo_id) { + return std::unique_ptr<SymbolFileDWARFDwo>( + new SymbolFileDWARFDwoDwp(this, m_obj_file, dwarf_cu, dwo_id)); +} + +bool SymbolFileDWARFDwp::LoadSectionData( + uint64_t dwo_id, lldb::SectionType sect_type, + lldb_private::DWARFDataExtractor &data) { + lldb_private::DWARFDataExtractor section_data; + if (!LoadRawSectionData(sect_type, section_data)) + return false; + + auto it = m_debug_cu_index_map.find(dwo_id); + if (it == m_debug_cu_index_map.end()) + return false; + + auto *offsets = + it->second->getOffset(lldbSectTypeToLlvmSectionKind(sect_type)); + if (offsets) { + data.SetData(section_data, offsets->Offset, offsets->Length); + } else { + data.SetData(section_data, 0, section_data.GetByteSize()); + } + return true; +} + +bool SymbolFileDWARFDwp::LoadRawSectionData( + lldb::SectionType sect_type, lldb_private::DWARFDataExtractor &data) { + std::lock_guard<std::mutex> lock(m_sections_mutex); + + auto it = m_sections.find(sect_type); + if (it != m_sections.end()) { + if (it->second.GetByteSize() == 0) + return false; + + data = it->second; + return true; + } + + const lldb_private::SectionList *section_list = + m_obj_file->GetSectionList(false /* update_module_section_list */); + if (section_list) { + lldb::SectionSP section_sp( + section_list->FindSectionByType(sect_type, true)); + if (section_sp) { + if (m_obj_file->ReadSectionData(section_sp.get(), data) != 0) { + m_sections[sect_type] = data; + return true; + } + } + } + m_sections[sect_type].Clear(); + return false; +} diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h new file mode 100644 index 0000000000000..a7372b9358b16 --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h @@ -0,0 +1,55 @@ +//===-- SymbolFileDWARFDwp.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARFDwp_SymbolFileDWARFDwp_h_ +#define SymbolFileDWARFDwp_SymbolFileDWARFDwp_h_ + +// C Includes +// C++ Includes +#include <memory> + +// Other libraries and framework includes +#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" + +// Project includes +#include "lldb/Core/Module.h" + +#include "DWARFDataExtractor.h" +#include "SymbolFileDWARFDwo.h" + +class SymbolFileDWARFDwp { +public: + static std::unique_ptr<SymbolFileDWARFDwp> + Create(lldb::ModuleSP module_sp, const lldb_private::FileSpec &file_spec); + + std::unique_ptr<SymbolFileDWARFDwo> + GetSymbolFileForDwoId(DWARFCompileUnit *dwarf_cu, uint64_t dwo_id); + + bool LoadSectionData(uint64_t dwo_id, lldb::SectionType sect_type, + lldb_private::DWARFDataExtractor &data); + +private: + explicit SymbolFileDWARFDwp(lldb::ModuleSP module_sp, + lldb::ObjectFileSP obj_file); + + bool LoadRawSectionData(lldb::SectionType sect_type, + lldb_private::DWARFDataExtractor &data); + + void InitDebugCUIndexMap(); + + lldb::ObjectFileSP m_obj_file; + + std::mutex m_sections_mutex; + std::map<lldb::SectionType, lldb_private::DWARFDataExtractor> m_sections; + + llvm::DWARFUnitIndex m_debug_cu_index; + std::map<uint64_t, const llvm::DWARFUnitIndex::Entry *> m_debug_cu_index_map; +}; + +#endif // SymbolFileDWARFDwp_SymbolFileDWARFDwp_h_ diff --git a/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp index b48de2e591e32..9b98ebe112a24 100644 --- a/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp +++ b/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp @@ -95,11 +95,11 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true); - return std::make_shared<Type>(type.getSymIndexId(), m_ast.GetSymbolFile(), - ConstString(udt->getName()), udt->getLength(), - nullptr, LLDB_INVALID_UID, - Type::eEncodingIsUID, decl, clang_type, - Type::eResolveStateForward); + return std::make_shared<lldb_private::Type>( + type.getSymIndexId(), m_ast.GetSymbolFile(), + ConstString(udt->getName()), udt->getLength(), nullptr, + LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, clang_type, + lldb_private::Type::eResolveStateForward); } else if (auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(&type)) { std::string name = enum_type->getName(); lldb::Encoding encoding = @@ -109,7 +109,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { m_ast.GetBuiltinTypeForEncodingAndBitSize(encoding, bytes * 8); CompilerType ast_enum = m_ast.CreateEnumerationType( - name.c_str(), tu_decl_ctx, decl, builtin_type); + name.c_str(), tu_decl_ctx, decl, builtin_type, false); auto enum_values = enum_type->findAllChildren<PDBSymbolData>(); while (auto enum_value = enum_values->getNext()) { if (enum_value->getDataKind() != PDB_DataKind::Constant) @@ -117,12 +117,12 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { AddEnumValue(ast_enum, *enum_value); } - return std::make_shared<Type>(type.getSymIndexId(), m_ast.GetSymbolFile(), - ConstString(name), bytes, nullptr, - LLDB_INVALID_UID, Type::eEncodingIsUID, decl, - ast_enum, Type::eResolveStateFull); + return std::make_shared<lldb_private::Type>( + type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), bytes, + nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, + ast_enum, lldb_private::Type::eResolveStateFull); } else if (auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(&type)) { - Type *target_type = + lldb_private::Type *target_type = m_ast.GetSymbolFile()->ResolveTypeUID(type_def->getTypeId()); std::string name = type_def->getName(); uint64_t bytes = type_def->getLength(); @@ -133,16 +133,17 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { m_ast.GetSymbolFile()->GetDeclContextForUID(target_type->GetID()); CompilerType ast_typedef = m_ast.CreateTypedefType(target_ast_type, name.c_str(), target_decl_ctx); - return std::make_shared<Type>( + return std::make_shared<lldb_private::Type>( type_def->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), - bytes, nullptr, target_type->GetID(), Type::eEncodingIsTypedefUID, decl, - ast_typedef, Type::eResolveStateFull); + bytes, nullptr, target_type->GetID(), + lldb_private::Type::eEncodingIsTypedefUID, decl, ast_typedef, + lldb_private::Type::eResolveStateFull); } else if (auto func_sig = llvm::dyn_cast<PDBSymbolTypeFunctionSig>(&type)) { auto arg_enum = func_sig->getArguments(); uint32_t num_args = arg_enum->getChildCount(); std::vector<CompilerType> arg_list(num_args); while (auto arg = arg_enum->getNext()) { - Type *arg_type = + lldb_private::Type *arg_type = m_ast.GetSymbolFile()->ResolveTypeUID(arg->getSymIndexId()); // If there's some error looking up one of the dependent types of this // function signature, bail. @@ -152,7 +153,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { arg_list.push_back(arg_ast_type); } auto pdb_return_type = func_sig->getReturnType(); - Type *return_type = + lldb_private::Type *return_type = m_ast.GetSymbolFile()->ResolveTypeUID(pdb_return_type->getSymIndexId()); // If there's some error looking up one of the dependent types of this // function signature, bail. @@ -167,23 +168,24 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { CompilerType func_sig_ast_type = m_ast.CreateFunctionType( return_ast_type, &arg_list[0], num_args, false, type_quals); - return std::make_shared<Type>( + return std::make_shared<lldb_private::Type>( func_sig->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(), 0, - nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, - func_sig_ast_type, Type::eResolveStateFull); + nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, + func_sig_ast_type, lldb_private::Type::eResolveStateFull); } else if (auto array_type = llvm::dyn_cast<PDBSymbolTypeArray>(&type)) { uint32_t num_elements = array_type->getCount(); uint32_t element_uid = array_type->getElementType()->getSymIndexId(); uint32_t bytes = array_type->getLength(); - Type *element_type = m_ast.GetSymbolFile()->ResolveTypeUID(element_uid); + lldb_private::Type *element_type = + m_ast.GetSymbolFile()->ResolveTypeUID(element_uid); CompilerType element_ast_type = element_type->GetFullCompilerType(); CompilerType array_ast_type = m_ast.CreateArrayType(element_ast_type, num_elements, false); - return std::make_shared<Type>( + return std::make_shared<lldb_private::Type>( array_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(), - bytes, nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, - array_ast_type, Type::eResolveStateFull); + bytes, nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, + decl, array_ast_type, lldb_private::Type::eResolveStateFull); } return nullptr; } diff --git a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp index f952696ab21dd..a25119684c288 100644 --- a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp +++ b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp @@ -127,13 +127,14 @@ SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp, SectionList *objfile_section_list = dsym_objfile_sp->GetSectionList(); static const SectionType g_sections[] = { - eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr, - eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugFrame, - eSectionTypeDWARFDebugInfo, eSectionTypeDWARFDebugLine, - eSectionTypeDWARFDebugLoc, eSectionTypeDWARFDebugMacInfo, - eSectionTypeDWARFDebugPubNames, eSectionTypeDWARFDebugPubTypes, - eSectionTypeDWARFDebugRanges, eSectionTypeDWARFDebugStr, - eSectionTypeDWARFDebugStrOffsets, eSectionTypeELFSymbolTable, + eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr, + eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugCuIndex, + eSectionTypeDWARFDebugFrame, eSectionTypeDWARFDebugInfo, + eSectionTypeDWARFDebugLine, eSectionTypeDWARFDebugLoc, + eSectionTypeDWARFDebugMacInfo, eSectionTypeDWARFDebugPubNames, + eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges, + eSectionTypeDWARFDebugStr, eSectionTypeDWARFDebugStrOffsets, + eSectionTypeELFSymbolTable, }; for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]); ++idx) { diff --git a/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp b/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp index 6d6abd62dad2a..b3fb05e652d96 100644 --- a/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp +++ b/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp @@ -220,6 +220,7 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp, // the original // gloal DBGSourcePath string. bool new_style_source_remapping_dictionary = false; + bool do_truncate_remapping_names = false; std::string original_DBGSourcePath_value = DBGSourcePath; if (plist_sp->GetAsDictionary()->HasKey("DBGVersion")) { @@ -233,6 +234,9 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp, if (version_number > 1) { new_style_source_remapping_dictionary = true; } + if (version_number == 2) { + do_truncate_remapping_names = true; + } } } @@ -242,7 +246,7 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp, ->GetAsDictionary(); remappings_dict->ForEach( [&module_sp, new_style_source_remapping_dictionary, - original_DBGSourcePath_value]( + original_DBGSourcePath_value, do_truncate_remapping_names]( ConstString key, StructuredData::Object *object) -> bool { if (object && object->GetAsString()) { @@ -264,6 +268,21 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp, } module_sp->GetSourceMappingList().Append( key, ConstString(DBGSourcePath), true); + // With version 2 of DBGSourcePathRemapping, we can chop off the + // last two filename parts from the source remapping and get a + // more general source remapping that still works. Add this as + // another option in addition to the full source path remap. + if (do_truncate_remapping_names) { + FileSpec build_path(key.AsCString(), false); + FileSpec source_path(DBGSourcePath.c_str(), false); + build_path.RemoveLastPathComponent(); + build_path.RemoveLastPathComponent(); + source_path.RemoveLastPathComponent(); + source_path.RemoveLastPathComponent(); + module_sp->GetSourceMappingList().Append( + ConstString(build_path.GetPath().c_str()), + ConstString(source_path.GetPath().c_str()), true); + } } return true; }); diff --git a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp index 3976f40dd8d17..f8aca4d1283b2 100644 --- a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp +++ b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp @@ -10,7 +10,6 @@ #include "UnwindAssemblyInstEmulation.h" #include "lldb/Core/Address.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/DumpDataExtractor.h" #include "lldb/Core/FormatEntity.h" @@ -19,6 +18,7 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Log.h" diff --git a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp index c171f0f4d2a00..b8dcd99a53e75 100644 --- a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp +++ b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp @@ -15,7 +15,6 @@ #include "llvm/Support/TargetSelect.h" #include "lldb/Core/Address.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/ABI.h" @@ -26,6 +25,7 @@ #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Target/UnwindAssembly.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Status.h" using namespace lldb; diff --git a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h index 97441d3629730..cec9803c8a494 100644 --- a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h +++ b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h @@ -12,13 +12,12 @@ #include "llvm-c/Disassembler.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/ConstString.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-forward.h" #include "lldb/lldb-private.h" -#include "lldb/Core/ArchSpec.h" -#include "lldb/Utility/ConstString.h" - #include <map> #include <vector> diff --git a/source/Symbol/ArmUnwindInfo.cpp b/source/Symbol/ArmUnwindInfo.cpp index 742c057e10e39..4da307bf0c326 100644 --- a/source/Symbol/ArmUnwindInfo.cpp +++ b/source/Symbol/ArmUnwindInfo.cpp @@ -46,7 +46,7 @@ bool ArmUnwindInfo::ArmExidxEntry::operator<(const ArmExidxEntry &other) const { return address < other.address; } -ArmUnwindInfo::ArmUnwindInfo(const ObjectFile &objfile, SectionSP &arm_exidx, +ArmUnwindInfo::ArmUnwindInfo(ObjectFile &objfile, SectionSP &arm_exidx, SectionSP &arm_extab) : m_byte_order(objfile.GetByteOrder()), m_arm_exidx_sp(arm_exidx), m_arm_extab_sp(arm_extab) { diff --git a/source/Symbol/ClangASTContext.cpp b/source/Symbol/ClangASTContext.cpp index c8738e6e55026..673124cc0de5f 100644 --- a/source/Symbol/ClangASTContext.cpp +++ b/source/Symbol/ClangASTContext.cpp @@ -70,7 +70,7 @@ #include "Plugins/ExpressionParser/Clang/ClangFunctionCaller.h" #include "Plugins/ExpressionParser/Clang/ClangUserExpression.h" #include "Plugins/ExpressionParser/Clang/ClangUtilityFunction.h" -#include "lldb/Core/ArchSpec.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Flags.h" #include "lldb/Core/DumpDataExtractor.h" @@ -435,75 +435,12 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) { // OpenCL and C++ both have bool, true, false keywords. Opts.Bool = Opts.OpenCL || Opts.CPlusPlus; - // if (Opts.CPlusPlus) - // Opts.CXXOperatorNames = !Args.hasArg(OPT_fno_operator_names); - // - // if (Args.hasArg(OPT_fobjc_gc_only)) - // Opts.setGCMode(LangOptions::GCOnly); - // else if (Args.hasArg(OPT_fobjc_gc)) - // Opts.setGCMode(LangOptions::HybridGC); - // - // if (Args.hasArg(OPT_print_ivar_layout)) - // Opts.ObjCGCBitmapPrint = 1; - // - // if (Args.hasArg(OPT_faltivec)) - // Opts.AltiVec = 1; - // - // if (Args.hasArg(OPT_pthread)) - // Opts.POSIXThreads = 1; - // - // llvm::StringRef Vis = getLastArgValue(Args, OPT_fvisibility, - // "default"); - // if (Vis == "default") Opts.setValueVisibilityMode(DefaultVisibility); - // else if (Vis == "hidden") - // Opts.setVisibilityMode(LangOptions::Hidden); - // else if (Vis == "protected") - // Opts.setVisibilityMode(LangOptions::Protected); - // else - // Diags.Report(diag::err_drv_invalid_value) - // << Args.getLastArg(OPT_fvisibility)->getAsString(Args) << Vis; - - // Opts.OverflowChecking = Args.hasArg(OPT_ftrapv); // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs // is specified, or -std is set to a conforming mode. Opts.Trigraphs = !Opts.GNUMode; - // if (Args.hasArg(OPT_trigraphs)) - // Opts.Trigraphs = 1; - // - // Opts.DollarIdents = Args.hasFlag(OPT_fdollars_in_identifiers, - // OPT_fno_dollars_in_identifiers, - // !Opts.AsmPreprocessor); - // Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings); - // Opts.Microsoft = Args.hasArg(OPT_fms_extensions); - // Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings); - // if (Args.hasArg(OPT_fno_lax_vector_conversions)) - // Opts.LaxVectorConversions = 0; - // Opts.Exceptions = Args.hasArg(OPT_fexceptions); - // Opts.RTTI = !Args.hasArg(OPT_fno_rtti); - // Opts.Blocks = Args.hasArg(OPT_fblocks); Opts.CharIsSigned = ArchSpec(triple).CharIsSignedByDefault(); - // Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar); - // Opts.Freestanding = Args.hasArg(OPT_ffreestanding); - // Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; - // Opts.AssumeSaneOperatorNew = - // !Args.hasArg(OPT_fno_assume_sane_operator_new); - // Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions); - // Opts.AccessControl = Args.hasArg(OPT_faccess_control); - // Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors); - // Opts.MathErrno = !Args.hasArg(OPT_fno_math_errno); - // Opts.InstantiationDepth = getLastArgIntValue(Args, OPT_ftemplate_depth, - // 99, - // Diags); - // Opts.NeXTRuntime = !Args.hasArg(OPT_fgnu_runtime); - // Opts.ObjCConstantStringClass = getLastArgValue(Args, - // OPT_fconstant_string_class); - // Opts.ObjCNonFragileABI = Args.hasArg(OPT_fobjc_nonfragile_abi); - // Opts.CatchUndefined = Args.hasArg(OPT_fcatch_undefined_behavior); - // Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls); - // Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); - // Opts.Static = Args.hasArg(OPT_static_define); Opts.OptimizeSize = 0; // FIXME: Eliminate this dependency. @@ -518,18 +455,6 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) { // // FIXME: This is affected by other options (-fno-inline). Opts.NoInlineDefine = !Opt; - - // unsigned SSP = getLastArgIntValue(Args, OPT_stack_protector, 0, Diags); - // switch (SSP) { - // default: - // Diags.Report(diag::err_drv_invalid_value) - // << Args.getLastArg(OPT_stack_protector)->getAsString(Args) << - // SSP; - // break; - // case 0: Opts.setStackProtectorMode(LangOptions::SSPOff); break; - // case 1: Opts.setStackProtectorMode(LangOptions::SSPOn); break; - // case 2: Opts.setStackProtectorMode(LangOptions::SSPReq); break; - // } } ClangASTContext::ClangASTContext(const char *target_triple) @@ -596,8 +521,9 @@ lldb::TypeSystemSP ClangASTContext::CreateInstance(lldb::LanguageType language, ast_sp->SetArchitecture(fixed_arch); ast_sp->m_scratch_ast_source_ap.reset( new ClangASTSource(target->shared_from_this())); + lldbassert(ast_sp->getFileManager()); ast_sp->m_scratch_ast_source_ap->InstallASTContext( - ast_sp->getASTContext()); + *ast_sp->getASTContext(), *ast_sp->getFileManager(), true); llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> proxy_ast_source( ast_sp->m_scratch_ast_source_ap->CreateProxy()); ast_sp->SetExternalSource(proxy_ast_source); @@ -1430,7 +1356,7 @@ static TemplateParameterList *CreateTemplateParameterList( is_typename, parameter_pack)); } } - + if (template_param_infos.packed_args && template_param_infos.packed_args->args.size()) { IdentifierInfo *identifier_info = nullptr; @@ -2168,21 +2094,21 @@ CompilerType ClangASTContext::GetOrCreateStructForIdentifier( CompilerType ClangASTContext::CreateEnumerationType(const char *name, DeclContext *decl_ctx, const Declaration &decl, - const CompilerType &integer_clang_type) { + const CompilerType &integer_clang_type, + bool is_scoped) { // TODO: Do something intelligent with the Declaration object passed in // like maybe filling in the SourceLocation with it... ASTContext *ast = getASTContext(); // TODO: ask about these... - // const bool IsScoped = false; // const bool IsFixed = false; EnumDecl *enum_decl = EnumDecl::Create( *ast, decl_ctx, SourceLocation(), SourceLocation(), name && name[0] ? &ast->Idents.get(name) : nullptr, nullptr, - false, // IsScoped - false, // IsScopedUsingClassTag - false); // IsFixed + is_scoped, // IsScoped + is_scoped, // IsScopedUsingClassTag + false); // IsFixed if (enum_decl) { // TODO: check if we should be setting the promotion type too? @@ -4350,6 +4276,9 @@ ClangASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) { break; case clang::Type::ObjCTypeParam: break; + + case clang::Type::DependentAddressSpace: + break; } // We don't know hot to display this type... return lldb::eTypeClassOther; @@ -5009,6 +4938,7 @@ lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type, case clang::BuiltinType::Half: case clang::BuiltinType::Float: + case clang::BuiltinType::Float16: case clang::BuiltinType::Float128: case clang::BuiltinType::Double: case clang::BuiltinType::LongDouble: @@ -5159,6 +5089,9 @@ lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type, break; case clang::Type::ObjCTypeParam: break; + + case clang::Type::DependentAddressSpace: + break; } count = 0; return lldb::eEncodingInvalid; @@ -5309,6 +5242,9 @@ lldb::Format ClangASTContext::GetFormat(lldb::opaque_compiler_type_t type) { break; case clang::Type::ObjCTypeParam: break; + + case clang::Type::DependentAddressSpace: + break; } // We don't know hot to display this type... return lldb::eFormatBytes; @@ -7538,99 +7474,122 @@ ClangASTContext::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) { return 0; } -CompilerType -ClangASTContext::GetTemplateArgument(lldb::opaque_compiler_type_t type, - size_t arg_idx, - lldb::TemplateArgumentKind &kind) { +const clang::ClassTemplateSpecializationDecl * +ClangASTContext::GetAsTemplateSpecialization( + lldb::opaque_compiler_type_t type) { if (!type) - return CompilerType(); + return nullptr; clang::QualType qual_type(GetCanonicalQualType(type)); const clang::Type::TypeClass type_class = qual_type->getTypeClass(); switch (type_class) { - case clang::Type::Record: - if (GetCompleteType(type)) { - const clang::CXXRecordDecl *cxx_record_decl = - qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) { - const clang::ClassTemplateSpecializationDecl *template_decl = - llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>( - cxx_record_decl); - if (template_decl && - arg_idx < template_decl->getTemplateArgs().size()) { - const clang::TemplateArgument &template_arg = - template_decl->getTemplateArgs()[arg_idx]; - switch (template_arg.getKind()) { - case clang::TemplateArgument::Null: - kind = eTemplateArgumentKindNull; - return CompilerType(); - - case clang::TemplateArgument::Type: - kind = eTemplateArgumentKindType; - return CompilerType(getASTContext(), template_arg.getAsType()); - - case clang::TemplateArgument::Declaration: - kind = eTemplateArgumentKindDeclaration; - return CompilerType(); - - case clang::TemplateArgument::Integral: - kind = eTemplateArgumentKindIntegral; - return CompilerType(getASTContext(), - template_arg.getIntegralType()); - - case clang::TemplateArgument::Template: - kind = eTemplateArgumentKindTemplate; - return CompilerType(); - - case clang::TemplateArgument::TemplateExpansion: - kind = eTemplateArgumentKindTemplateExpansion; - return CompilerType(); - - case clang::TemplateArgument::Expression: - kind = eTemplateArgumentKindExpression; - return CompilerType(); - - case clang::TemplateArgument::Pack: - kind = eTemplateArgumentKindPack; - return CompilerType(); - - default: - llvm_unreachable("Unhandled clang::TemplateArgument::ArgKind"); - } - } - } - } - break; + case clang::Type::Record: { + if (! GetCompleteType(type)) + return nullptr; + const clang::CXXRecordDecl *cxx_record_decl = + qual_type->getAsCXXRecordDecl(); + if (!cxx_record_decl) + return nullptr; + return llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>( + cxx_record_decl); + } case clang::Type::Typedef: - return (CompilerType(getASTContext(), - llvm::cast<clang::TypedefType>(qual_type) - ->getDecl() - ->getUnderlyingType())) - .GetTemplateArgument(arg_idx, kind); + return GetAsTemplateSpecialization(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()); case clang::Type::Auto: - return (CompilerType( - getASTContext(), - llvm::cast<clang::AutoType>(qual_type)->getDeducedType())) - .GetTemplateArgument(arg_idx, kind); + return GetAsTemplateSpecialization(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()); case clang::Type::Elaborated: - return (CompilerType( - getASTContext(), - llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType())) - .GetTemplateArgument(arg_idx, kind); + return GetAsTemplateSpecialization( + llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()); case clang::Type::Paren: - return (CompilerType(getASTContext(), - llvm::cast<clang::ParenType>(qual_type)->desugar())) - .GetTemplateArgument(arg_idx, kind); + return GetAsTemplateSpecialization( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); default: - break; + return nullptr; } - kind = eTemplateArgumentKindNull; - return CompilerType(); +} + +lldb::TemplateArgumentKind +ClangASTContext::GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, + size_t arg_idx) { + const clang::ClassTemplateSpecializationDecl *template_decl = + GetAsTemplateSpecialization(type); + if (! template_decl || arg_idx >= template_decl->getTemplateArgs().size()) + return eTemplateArgumentKindNull; + + switch (template_decl->getTemplateArgs()[arg_idx].getKind()) { + case clang::TemplateArgument::Null: + return eTemplateArgumentKindNull; + + case clang::TemplateArgument::NullPtr: + return eTemplateArgumentKindNullPtr; + + case clang::TemplateArgument::Type: + return eTemplateArgumentKindType; + + case clang::TemplateArgument::Declaration: + return eTemplateArgumentKindDeclaration; + + case clang::TemplateArgument::Integral: + return eTemplateArgumentKindIntegral; + + case clang::TemplateArgument::Template: + return eTemplateArgumentKindTemplate; + + case clang::TemplateArgument::TemplateExpansion: + return eTemplateArgumentKindTemplateExpansion; + + case clang::TemplateArgument::Expression: + return eTemplateArgumentKindExpression; + + case clang::TemplateArgument::Pack: + return eTemplateArgumentKindPack; + } + llvm_unreachable("Unhandled clang::TemplateArgument::ArgKind"); +} + +CompilerType +ClangASTContext::GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, + size_t idx) { + const clang::ClassTemplateSpecializationDecl *template_decl = + GetAsTemplateSpecialization(type); + if (!template_decl || idx >= template_decl->getTemplateArgs().size()) + return CompilerType(); + + const clang::TemplateArgument &template_arg = + template_decl->getTemplateArgs()[idx]; + if (template_arg.getKind() != clang::TemplateArgument::Type) + return CompilerType(); + + return CompilerType(getASTContext(), template_arg.getAsType()); +} + +llvm::Optional<CompilerType::IntegralTemplateArgument> +ClangASTContext::GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, + size_t idx) { + const clang::ClassTemplateSpecializationDecl *template_decl = + GetAsTemplateSpecialization(type); + if (! template_decl || idx >= template_decl->getTemplateArgs().size()) + return llvm::None; + + const clang::TemplateArgument &template_arg = + template_decl->getTemplateArgs()[idx]; + if (template_arg.getKind() != clang::TemplateArgument::Integral) + return llvm::None; + + return {{template_arg.getAsIntegral(), + CompilerType(getASTContext(), template_arg.getIntegralType())}}; } CompilerType ClangASTContext::GetTypeForFormatters(void *type) { @@ -10121,3 +10080,10 @@ PersistentExpressionState * ClangASTContextForExpressions::GetPersistentExpressionState() { return m_persistent_variables.get(); } + +clang::ExternalASTMerger & +ClangASTContextForExpressions::GetMergerUnchecked() { + lldbassert(m_scratch_ast_source_ap != nullptr); + return m_scratch_ast_source_ap->GetMergerUnchecked(); +} + diff --git a/source/Symbol/ClangExternalASTSourceCommon.cpp b/source/Symbol/ClangExternalASTSourceCommon.cpp index 7a1a0f23a7ce0..992a76352d927 100644 --- a/source/Symbol/ClangExternalASTSourceCommon.cpp +++ b/source/Symbol/ClangExternalASTSourceCommon.cpp @@ -10,6 +10,8 @@ #include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Utility/Stream.h" +#include <mutex> + using namespace lldb_private; uint64_t g_TotalSizeOfMetadata = 0; @@ -18,15 +20,19 @@ typedef llvm::DenseMap<clang::ExternalASTSource *, ClangExternalASTSourceCommon *> ASTSourceMap; -static ASTSourceMap &GetSourceMap() { +static ASTSourceMap &GetSourceMap(std::unique_lock<std::mutex> &guard) { // Intentionally leaked to avoid problems with global destructors. static ASTSourceMap *s_source_map = new ASTSourceMap; + static std::mutex s_mutex; + std::unique_lock<std::mutex> locked_guard(s_mutex); + guard.swap(locked_guard); return *s_source_map; } ClangExternalASTSourceCommon * ClangExternalASTSourceCommon::Lookup(clang::ExternalASTSource *source) { - ASTSourceMap &source_map = GetSourceMap(); + std::unique_lock<std::mutex> guard; + ASTSourceMap &source_map = GetSourceMap(guard); ASTSourceMap::iterator iter = source_map.find(source); @@ -40,11 +46,13 @@ ClangExternalASTSourceCommon::Lookup(clang::ExternalASTSource *source) { ClangExternalASTSourceCommon::ClangExternalASTSourceCommon() : clang::ExternalASTSource() { g_TotalSizeOfMetadata += m_metadata.size(); - GetSourceMap()[this] = this; + std::unique_lock<std::mutex> guard; + GetSourceMap(guard)[this] = this; } ClangExternalASTSourceCommon::~ClangExternalASTSourceCommon() { - GetSourceMap().erase(this); + std::unique_lock<std::mutex> guard; + GetSourceMap(guard).erase(this); g_TotalSizeOfMetadata -= m_metadata.size(); } diff --git a/source/Symbol/CompactUnwindInfo.cpp b/source/Symbol/CompactUnwindInfo.cpp index bc367496003e8..df71b17c09d0c 100644 --- a/source/Symbol/CompactUnwindInfo.cpp +++ b/source/Symbol/CompactUnwindInfo.cpp @@ -7,22 +7,18 @@ // //===----------------------------------------------------------------------===// -// C Includes -// C++ Includes -#include <algorithm> - -#include "lldb/Core/ArchSpec.h" +#include "lldb/Symbol/CompactUnwindInfo.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" -#include "lldb/Core/Section.h" -#include "lldb/Symbol/CompactUnwindInfo.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" +#include <algorithm> #include "llvm/Support/MathExtras.h" diff --git a/source/Symbol/CompilerType.cpp b/source/Symbol/CompilerType.cpp index e3880af27f22e..5d845361b03ce 100644 --- a/source/Symbol/CompilerType.cpp +++ b/source/Symbol/CompilerType.cpp @@ -690,15 +690,26 @@ size_t CompilerType::GetNumTemplateArguments() const { return 0; } -CompilerType -CompilerType::GetTemplateArgument(size_t idx, - lldb::TemplateArgumentKind &kind) const { +TemplateArgumentKind CompilerType::GetTemplateArgumentKind(size_t idx) const { + if (IsValid()) + return m_type_system->GetTemplateArgumentKind(m_type, idx); + return eTemplateArgumentKindNull; +} + +CompilerType CompilerType::GetTypeTemplateArgument(size_t idx) const { if (IsValid()) { - return m_type_system->GetTemplateArgument(m_type, idx, kind); + return m_type_system->GetTypeTemplateArgument(m_type, idx); } return CompilerType(); } +llvm::Optional<CompilerType::IntegralTemplateArgument> +CompilerType::GetIntegralTemplateArgument(size_t idx) const { + if (IsValid()) + return m_type_system->GetIntegralTemplateArgument(m_type, idx); + return llvm::None; +} + CompilerType CompilerType::GetTypeForFormatters() const { if (IsValid()) return m_type_system->GetTypeForFormatters(m_type); @@ -997,7 +1008,7 @@ bool CompilerType::ReadFromMemory(lldb_private::ExecutionContext *exe_ctx, if (addr == 0) return false; // The address is an address in this process, so just copy it - memcpy(dst, (uint8_t *)nullptr + addr, byte_size); + memcpy(dst, reinterpret_cast<uint8_t *>(addr), byte_size); return true; } else { Process *process = nullptr; diff --git a/source/Symbol/DWARFCallFrameInfo.cpp b/source/Symbol/DWARFCallFrameInfo.cpp index 9b1f8c694ccfe..572648d05f09b 100644 --- a/source/Symbol/DWARFCallFrameInfo.cpp +++ b/source/Symbol/DWARFCallFrameInfo.cpp @@ -7,22 +7,19 @@ // //===----------------------------------------------------------------------===// -// C Includes -// C++ Includes -#include <list> - -#include "lldb/Core/ArchSpec.h" +#include "lldb/Symbol/DWARFCallFrameInfo.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" #include "lldb/Core/dwarf.h" #include "lldb/Host/Host.h" -#include "lldb/Symbol/DWARFCallFrameInfo.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Timer.h" +#include <list> using namespace lldb; using namespace lldb_private; diff --git a/source/Symbol/JavaASTContext.cpp b/source/Symbol/JavaASTContext.cpp index ae4e9d5134b56..ff317eb19e97c 100644 --- a/source/Symbol/JavaASTContext.cpp +++ b/source/Symbol/JavaASTContext.cpp @@ -7,9 +7,7 @@ // //===----------------------------------------------------------------------===// -#include <sstream> - -#include "lldb/Core/ArchSpec.h" +#include "lldb/Symbol/JavaASTContext.h" #include "lldb/Core/DumpDataExtractor.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" @@ -17,11 +15,12 @@ #include "lldb/Core/ValueObject.h" #include "lldb/Expression/DWARFExpression.h" #include "lldb/Symbol/CompilerType.h" -#include "lldb/Symbol/JavaASTContext.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/Type.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Stream.h" +#include <sstream> #include "Plugins/SymbolFile/DWARF/DWARFASTParserJava.h" @@ -134,9 +133,9 @@ public: obj_load_address.SetValueType(Value::eValueTypeLoadAddress); Value result; - if (m_dynamic_type_id.Evaluate(exe_ctx->GetBestExecutionContextScope(), - nullptr, nullptr, 0, &obj_load_address, - nullptr, result, nullptr)) { + if (m_dynamic_type_id.Evaluate(exe_ctx->GetBestExecutionContextScope(), 0, + &obj_load_address, nullptr, result, + nullptr)) { Status error; lldb::addr_t type_id_addr = result.GetScalar().UInt(); @@ -315,9 +314,8 @@ public: ExecutionContextScope *exec_ctx_scope = value_obj->GetExecutionContextRef() .Lock(true) .GetBestExecutionContextScope(); - if (m_length_expression.Evaluate(exec_ctx_scope, nullptr, nullptr, 0, - nullptr, &obj_load_address, result, - nullptr)) + if (m_length_expression.Evaluate(exec_ctx_scope, 0, nullptr, + &obj_load_address, result, nullptr)) return result.GetScalar().UInt(); return UINT32_MAX; @@ -885,13 +883,6 @@ JavaASTContext::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) { return 0; } -CompilerType -JavaASTContext::GetTemplateArgument(lldb::opaque_compiler_type_t type, - size_t idx, - lldb::TemplateArgumentKind &kind) { - return CompilerType(); -} - uint32_t JavaASTContext::GetNumFields(lldb::opaque_compiler_type_t type) { if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) { diff --git a/source/Symbol/ObjectFile.cpp b/source/Symbol/ObjectFile.cpp index fd4180862c15b..7d73cb19d5083 100644 --- a/source/Symbol/ObjectFile.cpp +++ b/source/Symbol/ObjectFile.cpp @@ -348,6 +348,7 @@ AddressClass ObjectFile::GetAddressClass(addr_t file_addr) { case eSectionTypeDWARFDebugAbbrev: case eSectionTypeDWARFDebugAddr: case eSectionTypeDWARFDebugAranges: + case eSectionTypeDWARFDebugCuIndex: case eSectionTypeDWARFDebugFrame: case eSectionTypeDWARFDebugInfo: case eSectionTypeDWARFDebugLine: @@ -482,9 +483,9 @@ size_t ObjectFile::CopyData(lldb::offset_t offset, size_t length, return m_data.CopyData(offset, length, dst); } -size_t ObjectFile::ReadSectionData(const Section *section, +size_t ObjectFile::ReadSectionData(Section *section, lldb::offset_t section_offset, void *dst, - size_t dst_len) const { + size_t dst_len) { assert(section); section_offset *= section->GetTargetByteSize(); @@ -504,6 +505,9 @@ size_t ObjectFile::ReadSectionData(const Section *section, dst_len, error); } } else { + if (!section->IsRelocated()) + RelocateSection(section); + const lldb::offset_t section_file_size = section->GetFileSize(); if (section_offset < section_file_size) { const size_t section_bytes_left = section_file_size - section_offset; @@ -530,8 +534,8 @@ size_t ObjectFile::ReadSectionData(const Section *section, //---------------------------------------------------------------------- // Get the section data the file on disk //---------------------------------------------------------------------- -size_t ObjectFile::ReadSectionData(const Section *section, - DataExtractor §ion_data) const { +size_t ObjectFile::ReadSectionData(Section *section, + DataExtractor §ion_data) { // If some other objectfile owns this data, pass this to them. if (section->GetObjectFile() != this) return section->GetObjectFile()->ReadSectionData(section, section_data); @@ -557,22 +561,9 @@ size_t ObjectFile::ReadSectionData(const Section *section, } else { // The object file now contains a full mmap'ed copy of the object file data, // so just use this - return MemoryMapSectionData(section, section_data); - } -} - -size_t ObjectFile::MemoryMapSectionData(const Section *section, - DataExtractor §ion_data) const { - // If some other objectfile owns this data, pass this to them. - if (section->GetObjectFile() != this) - return section->GetObjectFile()->MemoryMapSectionData(section, - section_data); + if (!section->IsRelocated()) + RelocateSection(section); - if (IsInMemory()) { - return ReadSectionData(section, section_data); - } else { - // The object file now contains a full mmap'ed copy of the object file data, - // so just use this return GetData(section->GetFileOffset(), section->GetFileSize(), section_data); } @@ -693,3 +684,7 @@ Status ObjectFile::LoadInMemory(Target &target, bool set_pc) { } return error; } + +void ObjectFile::RelocateSection(lldb_private::Section *section) +{ +} diff --git a/source/Symbol/Symtab.cpp b/source/Symbol/Symtab.cpp index 3e2c965509d3c..4ac30649110fc 100644 --- a/source/Symbol/Symtab.cpp +++ b/source/Symbol/Symtab.cpp @@ -399,29 +399,6 @@ void Symtab::InitNameIndexes() { m_basename_to_index.SizeToFit(); m_method_to_index.Sort(); m_method_to_index.SizeToFit(); - - // static StreamFile a ("/tmp/a.txt"); - // - // count = m_basename_to_index.GetSize(); - // if (count) - // { - // for (size_t i=0; i<count; ++i) - // { - // if (m_basename_to_index.GetValueAtIndex(i, entry.value)) - // a.Printf ("%s BASENAME\n", - // m_symbols[entry.value].GetMangled().GetName().GetCString()); - // } - // } - // count = m_method_to_index.GetSize(); - // if (count) - // { - // for (size_t i=0; i<count; ++i) - // { - // if (m_method_to_index.GetValueAtIndex(i, entry.value)) - // a.Printf ("%s METHOD\n", - // m_symbols[entry.value].GetMangled().GetName().GetCString()); - // } - // } } } @@ -616,8 +593,10 @@ void Symtab::SortSymbolIndexesByValue(std::vector<uint32_t> &indexes, std::stable_sort(indexes.begin(), indexes.end(), comparator); // Remove any duplicates if requested - if (remove_duplicates) - std::unique(indexes.begin(), indexes.end()); + if (remove_duplicates) { + auto last = std::unique(indexes.begin(), indexes.end()); + indexes.erase(last, indexes.end()); + } } uint32_t Symtab::AppendSymbolIndexesWithName(const ConstString &symbol_name, diff --git a/source/Symbol/Type.cpp b/source/Symbol/Type.cpp index 53d9c5cc96a92..53bf3e8500558 100644 --- a/source/Symbol/Type.cpp +++ b/source/Symbol/Type.cpp @@ -404,7 +404,7 @@ bool Type::ReadFromMemory(ExecutionContext *exe_ctx, lldb::addr_t addr, // The address is an address in this process, so just copy it if (addr == 0) return false; - memcpy(dst, (uint8_t *)nullptr + addr, byte_size); + memcpy(dst, reinterpret_cast<uint8_t *>(addr), byte_size); return true; } else { if (exe_ctx) { diff --git a/source/Symbol/TypeSystem.cpp b/source/Symbol/TypeSystem.cpp index fa5e0bc7da6ed..b99f21e1e3471 100644 --- a/source/Symbol/TypeSystem.cpp +++ b/source/Symbol/TypeSystem.cpp @@ -23,19 +23,20 @@ #include "lldb/Symbol/CompilerType.h" using namespace lldb_private; +using namespace lldb; TypeSystem::TypeSystem(LLVMCastKind kind) : m_kind(kind), m_sym_file(nullptr) {} TypeSystem::~TypeSystem() {} -lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language, - Module *module) { +static lldb::TypeSystemSP CreateInstanceHelper(lldb::LanguageType language, + Module *module, Target *target) { uint32_t i = 0; TypeSystemCreateInstance create_callback; while ((create_callback = PluginManager::GetTypeSystemCreateCallbackAtIndex( i++)) != nullptr) { lldb::TypeSystemSP type_system_sp = - create_callback(language, module, nullptr); + create_callback(language, module, target); if (type_system_sp) return type_system_sp; } @@ -44,18 +45,13 @@ lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language, } lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language, - Target *target) { - uint32_t i = 0; - TypeSystemCreateInstance create_callback; - while ((create_callback = PluginManager::GetTypeSystemCreateCallbackAtIndex( - i++)) != nullptr) { - lldb::TypeSystemSP type_system_sp = - create_callback(language, nullptr, target); - if (type_system_sp) - return type_system_sp; - } + Module *module) { + return CreateInstanceHelper(language, module, nullptr); +} - return lldb::TypeSystemSP(); +lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language, + Target *target) { + return CreateInstanceHelper(language, nullptr, target); } bool TypeSystem::IsAnonymousType(lldb::opaque_compiler_type_t type) { @@ -105,6 +101,22 @@ CompilerType TypeSystem::GetTypeForFormatters(void *type) { return CompilerType(this, type); } +TemplateArgumentKind +TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx) { + return eTemplateArgumentKindNull; +} + +CompilerType TypeSystem::GetTypeTemplateArgument(opaque_compiler_type_t type, + size_t idx) { + return CompilerType(); +} + +llvm::Optional<CompilerType::IntegralTemplateArgument> +TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type, + size_t idx) { + return llvm::None; +} + LazyBool TypeSystem::ShouldPrintAsOneLiner(void *type, ValueObject *valobj) { return eLazyBoolCalculate; } diff --git a/source/Symbol/Variable.cpp b/source/Symbol/Variable.cpp index ff32aa7314657..1957bcef1f3a0 100644 --- a/source/Symbol/Variable.cpp +++ b/source/Symbol/Variable.cpp @@ -425,14 +425,8 @@ Status Variable::GetValuesForVariableExpressionPath( llvm::StringRef variable_sub_expr_path = variable_expr_path.drop_front(variable_name.size()); if (!variable_sub_expr_path.empty()) { - ValueObject::ExpressionPathScanEndReason reason_to_stop; - ValueObject::ExpressionPathEndResultType final_value_type; - ValueObject::GetValueForExpressionPathOptions options; - ValueObject::ExpressionPathAftermath final_task_on_target; - valobj_sp = variable_valobj_sp->GetValueForExpressionPath( - variable_sub_expr_path, &reason_to_stop, &final_value_type, options, - &final_task_on_target); + variable_sub_expr_path); if (!valobj_sp) { error.SetErrorStringWithFormat( "invalid expression path '%s' for variable '%s'", diff --git a/source/Target/PathMappingList.cpp b/source/Target/PathMappingList.cpp index b834a3600d0b1..782c6e49623c5 100644 --- a/source/Target/PathMappingList.cpp +++ b/source/Target/PathMappingList.cpp @@ -85,7 +85,6 @@ void PathMappingList::Insert(const ConstString &path, bool PathMappingList::Replace(const ConstString &path, const ConstString &replacement, uint32_t index, bool notify) { - iterator insert_iter; if (index >= m_pairs.size()) return false; ++m_mod_id; diff --git a/source/Target/Platform.cpp b/source/Target/Platform.cpp index 498facf8e0d02..5d60bb7915559 100644 --- a/source/Target/Platform.cpp +++ b/source/Target/Platform.cpp @@ -356,6 +356,12 @@ PlatformSP Platform::Create(const ArchSpec &arch, ArchSpec *platform_arch_ptr, return platform_sp; } +ArchSpec Platform::GetAugmentedArchSpec(Platform *platform, llvm::StringRef triple) { + if (platform) + return platform->GetAugmentedArchSpec(triple); + return HostInfo::GetAugmentedArchSpec(triple); +} + //------------------------------------------------------------------ /// Default Constructor //------------------------------------------------------------------ @@ -963,6 +969,34 @@ const ArchSpec &Platform::GetSystemArchitecture() { return m_system_arch; } +ArchSpec Platform::GetAugmentedArchSpec(llvm::StringRef triple) { + if (triple.empty()) + return ArchSpec(); + llvm::Triple normalized_triple(llvm::Triple::normalize(triple)); + if (!ArchSpec::ContainsOnlyArch(normalized_triple)) + return ArchSpec(triple); + + if (auto kind = HostInfo::ParseArchitectureKind(triple)) + return HostInfo::GetArchitecture(*kind); + + ArchSpec compatible_arch; + ArchSpec raw_arch(triple); + if (!IsCompatibleArchitecture(raw_arch, false, &compatible_arch)) + return raw_arch; + + if (!compatible_arch.IsValid()) + return ArchSpec(normalized_triple); + + const llvm::Triple &compatible_triple = compatible_arch.GetTriple(); + if (normalized_triple.getVendorName().empty()) + normalized_triple.setVendor(compatible_triple.getVendor()); + if (normalized_triple.getOSName().empty()) + normalized_triple.setOS(compatible_triple.getOS()); + if (normalized_triple.getEnvironmentName().empty()) + normalized_triple.setEnvironment(compatible_triple.getEnvironment()); + return ArchSpec(normalized_triple); +} + Status Platform::ConnectRemote(Args &args) { Status error; if (IsHost()) @@ -1162,7 +1196,7 @@ Platform::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, // open for stdin/out/err after we have already opened the master // so we can read/write stdin/out/err. int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); - if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd) { + if (pty_fd != PseudoTerminal::invalid_fd) { process_sp->SetSTDIOFileDescriptor(pty_fd); } } else { @@ -1316,14 +1350,18 @@ Status Platform::Unlink(const FileSpec &path) { return error; } -uint64_t Platform::ConvertMmapFlagsToPlatform(const ArchSpec &arch, - unsigned flags) { +MmapArgList Platform::GetMmapArgumentList(const ArchSpec &arch, addr_t addr, + addr_t length, unsigned prot, + unsigned flags, addr_t fd, + addr_t offset) { uint64_t flags_platform = 0; if (flags & eMmapFlagsPrivate) flags_platform |= MAP_PRIVATE; if (flags & eMmapFlagsAnon) flags_platform |= MAP_ANON; - return flags_platform; + + MmapArgList args({addr, length, prot, flags_platform, fd, offset}); + return args; } lldb_private::Status Platform::RunShellCommand( @@ -1874,6 +1912,12 @@ size_t Platform::GetSoftwareBreakpointTrapOpcode(Target &target, trap_opcode_size = sizeof(g_ppc_opcode); } break; + case llvm::Triple::ppc64le: { + static const uint8_t g_ppc64le_opcode[] = {0x08, 0x00, 0xe0, 0x7f}; // trap + trap_opcode = g_ppc64le_opcode; + trap_opcode_size = sizeof(g_ppc64le_opcode); + } break; + case llvm::Triple::x86: case llvm::Triple::x86_64: { static const uint8_t g_i386_opcode[] = {0xCC}; diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp index 6cbe289ef26be..8fb149fab0633 100644 --- a/source/Target/Process.cpp +++ b/source/Target/Process.cpp @@ -144,6 +144,9 @@ static PropertyDefinition g_properties[] = { {"optimization-warnings", OptionValue::eTypeBoolean, false, true, nullptr, nullptr, "If true, warn when stopped in code that is optimized where " "stepping and variable availability may not behave as expected."}, + {"stop-on-exec", OptionValue::eTypeBoolean, true, true, + nullptr, nullptr, + "If true, stop when a shared library is loaded or unloaded."}, {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}}; enum { @@ -155,7 +158,8 @@ enum { ePropertyStopOnSharedLibraryEvents, ePropertyDetachKeepsStopped, ePropertyMemCacheLineSize, - ePropertyWarningOptimization + ePropertyWarningOptimization, + ePropertyStopOnExec }; ProcessProperties::ProcessProperties(lldb_private::Process *process) @@ -272,6 +276,12 @@ bool ProcessProperties::GetWarningsOptimization() const { nullptr, idx, g_properties[idx].default_uint_value != 0); } +bool ProcessProperties::GetStopOnExec() const { + const uint32_t idx = ePropertyStopOnExec; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_properties[idx].default_uint_value != 0); +} + void ProcessInstanceInfo::Dump(Stream &s, Platform *platform) const { const char *cstr; if (m_pid != LLDB_INVALID_PROCESS_ID) @@ -480,8 +490,8 @@ Status ProcessLaunchCommandOptions::SetOptionValue( execution_context ? execution_context->GetTargetSP() : TargetSP(); PlatformSP platform_sp = target_sp ? target_sp->GetPlatform() : PlatformSP(); - if (!launch_info.GetArchitecture().SetTriple(option_arg, platform_sp.get())) - launch_info.GetArchitecture().SetTriple(option_arg); + launch_info.GetArchitecture() = + Platform::GetAugmentedArchSpec(platform_sp.get(), option_arg); } break; case 'A': // Disable ASLR. @@ -743,8 +753,7 @@ Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp, m_profile_data_comm_mutex(), m_profile_data(), m_iohandler_sync(0), m_memory_cache(*this), m_allocated_memory_cache(*this), m_should_detach(false), m_next_event_action_ap(), m_public_run_lock(), - m_private_run_lock(), m_stop_info_override_callback(nullptr), - m_finalizing(false), m_finalize_called(false), + m_private_run_lock(), m_finalizing(false), m_finalize_called(false), m_clear_thread_plans_on_stop(false), m_force_next_event_delivery(false), m_last_broadcast_state(eStateInvalid), m_destroy_in_process(false), m_can_interpret_function_calls(false), m_warnings_issued(), @@ -871,7 +880,6 @@ void Process::Finalize() { m_language_runtimes.clear(); m_instrumentation_runtimes.clear(); m_next_event_action_ap.reset(); - m_stop_info_override_callback = nullptr; // Clear the last natural stop ID since it has a strong // reference to this process m_mod_id.SetStopEventForLastNaturalStopID(EventSP()); @@ -1562,7 +1570,6 @@ uint32_t Process::AssignIndexIDToThread(uint64_t thread_id) { } StateType Process::GetState() { - // If any other threads access this we will need a mutex for it return m_public_state.GetValue(); } @@ -1621,7 +1628,12 @@ Status Process::Resume() { log->Printf("Process::Resume: -- TrySetRunning failed, not resuming."); return error; } - return PrivateResume(); + Status error = PrivateResume(); + if (!error.Success()) { + // Undo running state change + m_public_run_lock.SetStopped(); + } + return error; } Status Process::ResumeSynchronous(Stream *stream) { @@ -1650,6 +1662,9 @@ Status Process::ResumeSynchronous(Stream *stream) { error.SetErrorStringWithFormat( "process not in stopped state after synchronous resume: %s", StateAsCString(state)); + } else { + // Undo running state change + m_public_run_lock.SetStopped(); } // Undo the hijacking of process events... @@ -2712,7 +2727,6 @@ Status Process::Launch(ProcessLaunchInfo &launch_info) { m_system_runtime_ap.reset(); m_os_ap.reset(); m_process_input_reader.reset(); - m_stop_info_override_callback = nullptr; Module *exe_module = GetTarget().GetExecutableModulePointer(); if (exe_module) { @@ -2800,9 +2814,6 @@ Status Process::Launch(ProcessLaunchInfo &launch_info) { else StartPrivateStateThread(); - m_stop_info_override_callback = - GetTarget().GetArchitecture().GetStopInfoOverrideCallback(); - // Target was stopped at entry as was intended. Need to notify the // listeners // about it. @@ -2986,7 +2997,6 @@ Status Process::Attach(ProcessAttachInfo &attach_info) { m_jit_loaders_ap.reset(); m_system_runtime_ap.reset(); m_os_ap.reset(); - m_stop_info_override_callback = nullptr; lldb::pid_t attach_pid = attach_info.GetProcessID(); Status error; @@ -3219,8 +3229,6 @@ void Process::CompleteAttach() { : "<none>"); } } - - m_stop_info_override_callback = process_arch.GetStopInfoOverrideCallback(); } Status Process::ConnectRemote(Stream *strm, llvm::StringRef remote_url) { @@ -5849,7 +5857,6 @@ void Process::DidExec() { m_instrumentation_runtimes.clear(); m_thread_list.DiscardThreadPlans(); m_memory_cache.Clear(true); - m_stop_info_override_callback = nullptr; DoDidExec(); CompleteAttach(); // Flush the process (threads and all stack frames) after running diff --git a/source/Target/ProcessLaunchInfo.cpp b/source/Target/ProcessLaunchInfo.cpp index 3fa40dcc5cab2..284df9fd8b58c 100644 --- a/source/Target/ProcessLaunchInfo.cpp +++ b/source/Target/ProcessLaunchInfo.cpp @@ -39,10 +39,9 @@ using namespace lldb_private; ProcessLaunchInfo::ProcessLaunchInfo() : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(0), - m_file_actions(), m_pty(new lldb_utility::PseudoTerminal), - m_resume_count(0), m_monitor_callback(nullptr), - m_monitor_callback_baton(nullptr), m_monitor_signals(false), - m_listener_sp(), m_hijack_listener_sp() {} + m_file_actions(), m_pty(new PseudoTerminal), m_resume_count(0), + m_monitor_callback(nullptr), m_monitor_callback_baton(nullptr), + m_monitor_signals(false), m_listener_sp(), m_hijack_listener_sp() {} ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec &stdin_file_spec, const FileSpec &stdout_file_spec, @@ -50,10 +49,9 @@ ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec &stdin_file_spec, const FileSpec &working_directory, uint32_t launch_flags) : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(launch_flags), - m_file_actions(), m_pty(new lldb_utility::PseudoTerminal), - m_resume_count(0), m_monitor_callback(nullptr), - m_monitor_callback_baton(nullptr), m_monitor_signals(false), - m_listener_sp(), m_hijack_listener_sp() { + m_file_actions(), m_pty(new PseudoTerminal), m_resume_count(0), + m_monitor_callback(nullptr), m_monitor_callback_baton(nullptr), + m_monitor_signals(false), m_listener_sp(), m_hijack_listener_sp() { if (stdin_file_spec) { FileAction file_action; const bool read = true; diff --git a/source/Target/RegisterContext.cpp b/source/Target/RegisterContext.cpp index 66164c175e416..28beb7bcb5e88 100644 --- a/source/Target/RegisterContext.cpp +++ b/source/Target/RegisterContext.cpp @@ -93,10 +93,9 @@ RegisterContext::UpdateDynamicRegisterSize(const lldb_private::ArchSpec &arch, Value result; Status error; const lldb::offset_t offset = 0; - if (dwarf_expr.Evaluate(&exe_ctx, nullptr, nullptr, this, opcode_ctx, - dwarf_data, nullptr, offset, dwarf_opcode_len, - eRegisterKindDWARF, nullptr, nullptr, result, - &error)) { + if (dwarf_expr.Evaluate(&exe_ctx, this, opcode_ctx, dwarf_data, nullptr, + offset, dwarf_opcode_len, eRegisterKindDWARF, nullptr, + nullptr, result, &error)) { expr_result = result.GetScalar().SInt(-1); switch (expr_result) { case 0: @@ -457,132 +456,3 @@ bool RegisterContext::ConvertBetweenRegisterKinds(lldb::RegisterKind source_rk, } return false; } - -// bool -// RegisterContext::ReadRegisterValue (uint32_t reg, Scalar &value) -//{ -// DataExtractor data; -// if (!ReadRegisterBytes (reg, data)) -// return false; -// -// const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg); -// uint32_t offset = 0; -// switch (reg_info->encoding) -// { -// case eEncodingInvalid: -// case eEncodingVector: -// break; -// -// case eEncodingUint: -// switch (reg_info->byte_size) -// { -// case 1: -// { -// value = data.GetU8 (&offset); -// return true; -// } -// case 2: -// { -// value = data.GetU16 (&offset); -// return true; -// } -// case 4: -// { -// value = data.GetU32 (&offset); -// return true; -// } -// case 8: -// { -// value = data.GetU64 (&offset); -// return true; -// } -// } -// break; -// case eEncodingSint: -// switch (reg_info->byte_size) -// { -// case 1: -// { -// int8_t v; -// if (data.ExtractBytes (0, sizeof (int8_t), -// endian::InlHostByteOrder(), &v) != sizeof (int8_t)) -// return false; -// value = v; -// return true; -// } -// case 2: -// { -// int16_t v; -// if (data.ExtractBytes (0, sizeof (int16_t), -// endian::InlHostByteOrder(), &v) != sizeof (int16_t)) -// return false; -// value = v; -// return true; -// } -// case 4: -// { -// int32_t v; -// if (data.ExtractBytes (0, sizeof (int32_t), -// endian::InlHostByteOrder(), &v) != sizeof (int32_t)) -// return false; -// value = v; -// return true; -// } -// case 8: -// { -// int64_t v; -// if (data.ExtractBytes (0, sizeof (int64_t), -// endian::InlHostByteOrder(), &v) != sizeof (int64_t)) -// return false; -// value = v; -// return true; -// } -// } -// break; -// case eEncodingIEEE754: -// switch (reg_info->byte_size) -// { -// case sizeof (float): -// { -// float v; -// if (data.ExtractBytes (0, sizeof (float), -// endian::InlHostByteOrder(), &v) != sizeof (float)) -// return false; -// value = v; -// return true; -// } -// case sizeof (double): -// { -// double v; -// if (data.ExtractBytes (0, sizeof (double), -// endian::InlHostByteOrder(), &v) != sizeof (double)) -// return false; -// value = v; -// return true; -// } -// case sizeof (long double): -// { -// double v; -// if (data.ExtractBytes (0, sizeof (long double), -// endian::InlHostByteOrder(), &v) != sizeof (long double)) -// return false; -// value = v; -// return true; -// } -// } -// break; -// } -// return false; -//} -// -// bool -// RegisterContext::WriteRegisterValue (uint32_t reg, const Scalar &value) -//{ -// DataExtractor data; -// if (!value.IsValid()) -// return false; -// if (!value.GetData (data)) -// return false; -// -// return WriteRegisterBytes (reg, data); -//} diff --git a/source/Target/StackFrame.cpp b/source/Target/StackFrame.cpp index 30fceb11c11f3..dd44eac8e50c2 100644 --- a/source/Target/StackFrame.cpp +++ b/source/Target/StackFrame.cpp @@ -1089,8 +1089,8 @@ bool StackFrame::GetFrameBaseValue(Scalar &frame_base, Status *error_ptr) { exe_ctx.GetTargetPtr()); if (m_sc.function->GetFrameBaseExpression().Evaluate( - &exe_ctx, nullptr, nullptr, nullptr, loclist_base_addr, nullptr, - nullptr, expr_value, &m_frame_base_error) == false) { + &exe_ctx, nullptr, loclist_base_addr, nullptr, nullptr, + expr_value, &m_frame_base_error) == false) { // We should really have an error if evaluate returns, but in case // we don't, lets set the error to something at least. if (m_frame_base_error.Success()) diff --git a/source/Target/StopInfo.cpp b/source/Target/StopInfo.cpp index 6af5ce1b2ebf9..652ad8a054457 100644 --- a/source/Target/StopInfo.cpp +++ b/source/Target/StopInfo.cpp @@ -393,7 +393,10 @@ protected: for (size_t j = 0; j < num_owners; j++) { lldb::BreakpointLocationSP bp_loc_sp = site_locations.GetByIndex(j); - + StreamString loc_desc; + if (log) { + bp_loc_sp->GetDescription(&loc_desc, eDescriptionLevelBrief); + } // If another action disabled this breakpoint or its location, then // don't run the actions. if (!bp_loc_sp->IsEnabled() || @@ -405,16 +408,16 @@ protected: // this thread. Skip the ones that aren't: if (!bp_loc_sp->ValidForThisThread(thread_sp.get())) { if (log) { - StreamString s; - bp_loc_sp->GetDescription(&s, eDescriptionLevelBrief); log->Printf("Breakpoint %s hit on thread 0x%llx but it was not " "for this thread, continuing.", - s.GetData(), static_cast<unsigned long long>( + loc_desc.GetData(), static_cast<unsigned long long>( thread_sp->GetID())); } continue; } + internal_breakpoint = bp_loc_sp->GetBreakpoint().IsInternal(); + // First run the precondition, but since the precondition is per // breakpoint, only run it once // per breakpoint. @@ -458,11 +461,10 @@ protected: error_sp->Flush(); } else { if (log) { - StreamString s; - bp_loc_sp->GetDescription(&s, eDescriptionLevelBrief); log->Printf("Condition evaluated for breakpoint %s on thread " "0x%llx conditon_says_stop: %i.", - s.GetData(), static_cast<unsigned long long>( + loc_desc.GetData(), + static_cast<unsigned long long>( thread_sp->GetID()), condition_says_stop); } @@ -477,7 +479,26 @@ protected: } } - bool callback_says_stop; + // Check the auto-continue bit on the location, do this before the + // callback since it may change this, but that would be for the + // NEXT hit. Note, you might think you could check auto-continue + // before the condition, and not evaluate the condition if it says + // to continue. But failing the condition means the breakpoint was + // effectively NOT HIT. So these two states are different. + bool auto_continue_says_stop = true; + if (bp_loc_sp->IsAutoContinue()) + { + if (log) + log->Printf("Continuing breakpoint %s as AutoContinue was set.", + loc_desc.GetData()); + // We want this stop reported, so you will know we auto-continued + // but only for external breakpoints: + if (!internal_breakpoint) + thread_sp->SetShouldReportStop(eVoteYes); + auto_continue_says_stop = false; + } + + bool callback_says_stop = true; // FIXME: For now the callbacks have to run in async mode - the // first time we restart we need @@ -493,11 +514,8 @@ protected: debugger.SetAsyncExecution(old_async); - if (callback_says_stop) + if (callback_says_stop && auto_continue_says_stop) m_should_stop = true; - - if (m_should_stop && !bp_loc_sp->GetBreakpoint().IsInternal()) - internal_breakpoint = false; // If we are going to stop for this breakpoint, then remove the // breakpoint. @@ -506,7 +524,6 @@ protected: thread_sp->GetProcess()->GetTarget().RemoveBreakpointByID( bp_loc_sp->GetBreakpoint().GetID()); } - // Also make sure that the callback hasn't continued the target. // If it did, when we'll set m_should_start to false and get out of // here. @@ -1071,6 +1088,10 @@ private: ExpressionVariableSP m_expression_variable_sp; }; +//---------------------------------------------------------------------- +// StopInfoExec +//---------------------------------------------------------------------- + class StopInfoExec : public StopInfo { public: StopInfoExec(Thread &thread) @@ -1078,6 +1099,13 @@ public: ~StopInfoExec() override = default; + bool ShouldStop(Event *event_ptr) override { + ThreadSP thread_sp(m_thread_wp.lock()); + if (thread_sp) + return thread_sp->GetProcess()->GetStopOnExec(); + return false; + } + StopReason GetStopReason() const override { return eStopReasonExec; } const char *GetDescription() override { return "exec"; } diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp index d97f651ca08b4..903f50887fec0 100644 --- a/source/Target/Target.cpp +++ b/source/Target/Target.cpp @@ -26,6 +26,7 @@ #include "lldb/Core/Event.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" #include "lldb/Core/SourceManager.h" #include "lldb/Core/State.h" @@ -65,6 +66,16 @@ using namespace lldb_private; constexpr std::chrono::milliseconds EvaluateExpressionOptions::default_timeout; +Target::Arch::Arch(const ArchSpec &spec) + : m_spec(spec), + m_plugin_up(PluginManager::CreateArchitectureInstance(spec)) {} + +const Target::Arch& Target::Arch::operator=(const ArchSpec &spec) { + m_spec = spec; + m_plugin_up = PluginManager::CreateArchitectureInstance(spec); + return *this; +} + ConstString &Target::GetStaticBroadcasterClass() { static ConstString class_name("lldb.target"); return class_name; @@ -76,12 +87,12 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, Broadcaster(debugger.GetBroadcasterManager(), Target::GetStaticBroadcasterClass().AsCString()), ExecutionContextScope(), m_debugger(debugger), m_platform_sp(platform_sp), - m_mutex(), m_arch(target_arch), m_images(this), m_section_load_history(), - m_breakpoint_list(false), m_internal_breakpoint_list(true), - m_watchpoint_list(), m_process_sp(), m_search_filter_sp(), - m_image_search_paths(ImageSearchPathsChanged, this), m_ast_importer_sp(), - m_source_manager_ap(), m_stop_hooks(), m_stop_hook_next_id(0), - m_valid(true), m_suppress_stop_hooks(false), + m_mutex(), m_arch(target_arch), + m_images(this), m_section_load_history(), m_breakpoint_list(false), + m_internal_breakpoint_list(true), m_watchpoint_list(), m_process_sp(), + m_search_filter_sp(), m_image_search_paths(ImageSearchPathsChanged, this), + m_ast_importer_sp(), m_source_manager_ap(), m_stop_hooks(), + m_stop_hook_next_id(0), m_valid(true), m_suppress_stop_hooks(false), m_is_dummy_target(is_dummy_target) { @@ -96,10 +107,11 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); if (log) log->Printf("%p Target::Target()", static_cast<void *>(this)); - if (m_arch.IsValid()) { - LogIfAnyCategoriesSet( - LIBLLDB_LOG_TARGET, "Target::Target created with architecture %s (%s)", - m_arch.GetArchitectureName(), m_arch.GetTriple().getTriple().c_str()); + if (target_arch.IsValid()) { + LogIfAnyCategoriesSet(LIBLLDB_LOG_TARGET, + "Target::Target created with architecture %s (%s)", + target_arch.GetArchitectureName(), + target_arch.GetTriple().getTriple().c_str()); } } @@ -123,6 +135,13 @@ void Target::PrimeFromDummyTarget(Target *target) { BreakpointSP new_bp(new Breakpoint(*this, *breakpoint_sp.get())); AddBreakpoint(new_bp, false); } + + for (auto bp_name_entry : target->m_breakpoint_names) + { + + BreakpointName *new_bp_name = new BreakpointName(*bp_name_entry.second); + AddBreakpointName(new_bp_name); + } } void Target::Dump(Stream *s, lldb::DescriptionLevel description_level) { @@ -243,7 +262,7 @@ void Target::Destroy() { m_valid = false; DeleteCurrentProcess(); m_platform_sp.reset(); - m_arch.Clear(); + m_arch = ArchSpec(); ClearModules(true); m_section_load_history.Clear(); const bool notify = false; @@ -601,6 +620,112 @@ void Target::AddBreakpoint(lldb::BreakpointSP bp_sp, bool internal) { } } +void Target::AddNameToBreakpoint(BreakpointID &id, + const char *name, + Status &error) + { + BreakpointSP bp_sp + = m_breakpoint_list.FindBreakpointByID(id.GetBreakpointID()); + if (!bp_sp) + { + StreamString s; + id.GetDescription(&s, eDescriptionLevelBrief); + error.SetErrorStringWithFormat("Could not find breakpoint %s", + s.GetData()); + return; + } + AddNameToBreakpoint(bp_sp, name, error); + } + +void Target::AddNameToBreakpoint(BreakpointSP &bp_sp, + const char *name, + Status &error) + { + if (!bp_sp) + return; + + BreakpointName *bp_name = FindBreakpointName(ConstString(name), true, error); + if (!bp_name) + return; + + bp_name->ConfigureBreakpoint(bp_sp); + bp_sp->AddName(name); + } + +void Target::AddBreakpointName(BreakpointName *bp_name) { + m_breakpoint_names.insert(std::make_pair(bp_name->GetName(), bp_name)); +} + +BreakpointName *Target::FindBreakpointName(const ConstString &name, + bool can_create, + Status &error) +{ + BreakpointID::StringIsBreakpointName(name.GetStringRef(), error); + if (!error.Success()) + return nullptr; + + BreakpointNameList::iterator iter = m_breakpoint_names.find(name); + if (iter == m_breakpoint_names.end()) { + if (!can_create) + { + error.SetErrorStringWithFormat("Breakpoint name \"%s\" doesn't exist and " + "can_create is false.", name.AsCString()); + return nullptr; + } + + iter = m_breakpoint_names.insert(std::make_pair(name, + new BreakpointName(name))) + .first; + } + return (iter->second); +} + +void +Target::DeleteBreakpointName(const ConstString &name) +{ + BreakpointNameList::iterator iter = m_breakpoint_names.find(name); + + if (iter != m_breakpoint_names.end()) { + const char *name_cstr = name.AsCString(); + m_breakpoint_names.erase(iter); + for (auto bp_sp : m_breakpoint_list.Breakpoints()) + bp_sp->RemoveName(name_cstr); + } +} + +void Target::RemoveNameFromBreakpoint(lldb::BreakpointSP &bp_sp, + const ConstString &name) +{ + bp_sp->RemoveName(name.AsCString()); +} + +void Target::ConfigureBreakpointName(BreakpointName &bp_name, + const BreakpointOptions &new_options, + const BreakpointName::Permissions &new_permissions) +{ + bp_name.GetOptions().CopyOverSetOptions(new_options); + bp_name.GetPermissions().MergeInto(new_permissions); + ApplyNameToBreakpoints(bp_name); +} + +void Target::ApplyNameToBreakpoints(BreakpointName &bp_name) { + BreakpointList bkpts_with_name(false); + m_breakpoint_list.FindBreakpointsByName(bp_name.GetName().AsCString(), + bkpts_with_name); + + for (auto bp_sp : bkpts_with_name.Breakpoints()) + bp_name.ConfigureBreakpoint(bp_sp); +} + +void Target::GetBreakpointNames(std::vector<std::string> &names) +{ + names.clear(); + for (auto bp_name : m_breakpoint_names) { + names.push_back(bp_name.first.AsCString()); + } + std::sort(names.begin(), names.end()); +} + bool Target::ProcessIsValid() { return (m_process_sp && m_process_sp->IsAlive()); } @@ -703,6 +828,17 @@ WatchpointSP Target::CreateWatchpoint(lldb::addr_t addr, size_t size, return wp_sp; } +void Target::RemoveAllowedBreakpoints () +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("Target::%s \n", __FUNCTION__); + + m_breakpoint_list.RemoveAllowed(true); + + m_last_created_breakpoint.reset(); +} + void Target::RemoveAllBreakpoints(bool internal_also) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); if (log) @@ -727,6 +863,14 @@ void Target::DisableAllBreakpoints(bool internal_also) { m_internal_breakpoint_list.SetEnabledAll(false); } +void Target::DisableAllowedBreakpoints() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("Target::%s", __FUNCTION__); + + m_breakpoint_list.SetEnabledAllowed(false); +} + void Target::EnableAllBreakpoints(bool internal_also) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); if (log) @@ -738,6 +882,14 @@ void Target::EnableAllBreakpoints(bool internal_also) { m_internal_breakpoint_list.SetEnabledAll(true); } +void Target::EnableAllowedBreakpoints() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("Target::%s", __FUNCTION__); + + m_breakpoint_list.SetEnabledAllowed(true); +} + bool Target::RemoveBreakpointByID(break_id_t break_id) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); if (log) @@ -1226,8 +1378,8 @@ void Target::ClearModules(bool delete_locations) { void Target::DidExec() { // When a process exec's we need to know about it so we can do some cleanup. - m_breakpoint_list.RemoveInvalidLocations(m_arch); - m_internal_breakpoint_list.RemoveInvalidLocations(m_arch); + m_breakpoint_list.RemoveInvalidLocations(m_arch.GetSpec()); + m_internal_breakpoint_list.RemoveInvalidLocations(m_arch.GetSpec()); } void Target::SetExecutableModule(ModuleSP &executable_sp, @@ -1245,13 +1397,12 @@ void Target::SetExecutableModule(ModuleSP &executable_sp, // If we haven't set an architecture yet, reset our architecture based on // what we found in the executable module. - if (!m_arch.IsValid()) { + if (!m_arch.GetSpec().IsValid()) { m_arch = executable_sp->GetArchitecture(); - if (log) - log->Printf("Target::SetExecutableModule setting architecture to %s " - "(%s) based on executable file", - m_arch.GetArchitectureName(), - m_arch.GetTriple().getTriple().c_str()); + LLDB_LOG(log, + "setting architecture to {0} ({1}) based on executable file", + m_arch.GetSpec().GetArchitectureName(), + m_arch.GetSpec().GetTriple().getTriple()); } FileSpecList dependent_files; @@ -1269,7 +1420,7 @@ void Target::SetExecutableModule(ModuleSP &executable_sp, else platform_dependent_file_spec = dependent_file_spec; - ModuleSpec module_spec(platform_dependent_file_spec, m_arch); + ModuleSpec module_spec(platform_dependent_file_spec, m_arch.GetSpec()); ModuleSP image_module_sp(GetSharedModule(module_spec)); if (image_module_sp) { ObjectFile *objfile = image_module_sp->GetObjectFile(); @@ -1283,21 +1434,21 @@ void Target::SetExecutableModule(ModuleSP &executable_sp, bool Target::SetArchitecture(const ArchSpec &arch_spec) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TARGET)); - bool missing_local_arch = !m_arch.IsValid(); + bool missing_local_arch = !m_arch.GetSpec().IsValid(); bool replace_local_arch = true; bool compatible_local_arch = false; ArchSpec other(arch_spec); if (!missing_local_arch) { - if (m_arch.IsCompatibleMatch(arch_spec)) { - other.MergeFrom(m_arch); + if (m_arch.GetSpec().IsCompatibleMatch(arch_spec)) { + other.MergeFrom(m_arch.GetSpec()); - if (m_arch.IsCompatibleMatch(other)) { + if (m_arch.GetSpec().IsCompatibleMatch(other)) { compatible_local_arch = true; bool arch_changed, vendor_changed, os_changed, os_ver_changed, env_changed; - m_arch.PiecewiseTripleCompare(other, arch_changed, vendor_changed, + m_arch.GetSpec().PiecewiseTripleCompare(other, arch_changed, vendor_changed, os_changed, os_ver_changed, env_changed); if (!arch_changed && !vendor_changed && !os_changed && !env_changed) @@ -1311,10 +1462,9 @@ bool Target::SetArchitecture(const ArchSpec &arch_spec) { // update the architecture, unless the one we already have is more specified if (replace_local_arch) m_arch = other; - if (log) - log->Printf("Target::SetArchitecture set architecture to %s (%s)", - m_arch.GetArchitectureName(), - m_arch.GetTriple().getTriple().c_str()); + LLDB_LOG(log, "set architecture to {0} ({1})", + m_arch.GetSpec().GetArchitectureName(), + m_arch.GetSpec().GetTriple().getTriple()); return true; } @@ -1351,12 +1501,12 @@ bool Target::SetArchitecture(const ArchSpec &arch_spec) { bool Target::MergeArchitecture(const ArchSpec &arch_spec) { if (arch_spec.IsValid()) { - if (m_arch.IsCompatibleMatch(arch_spec)) { + if (m_arch.GetSpec().IsCompatibleMatch(arch_spec)) { // The current target arch is compatible with "arch_spec", see if we // can improve our current architecture using bits from "arch_spec" // Merge bits from arch_spec into "merged_arch" and set our architecture - ArchSpec merged_arch(m_arch); + ArchSpec merged_arch(m_arch.GetSpec()); merged_arch.MergeFrom(arch_spec); return SetArchitecture(merged_arch); } else { @@ -1684,8 +1834,8 @@ size_t Target::ReadScalarIntegerFromMemory(const Address &addr, size_t bytes_read = ReadMemory(addr, prefer_file_cache, &uval, byte_size, error); if (bytes_read == byte_size) { - DataExtractor data(&uval, sizeof(uval), m_arch.GetByteOrder(), - m_arch.GetAddressByteSize()); + DataExtractor data(&uval, sizeof(uval), m_arch.GetSpec().GetByteOrder(), + m_arch.GetSpec().GetAddressByteSize()); lldb::offset_t offset = 0; if (byte_size <= 4) scalar = data.GetMaxU32(&offset, byte_size); @@ -1719,7 +1869,7 @@ bool Target::ReadPointerFromMemory(const Address &addr, bool prefer_file_cache, Status &error, Address &pointer_addr) { Scalar scalar; if (ReadScalarIntegerFromMemory(addr, prefer_file_cache, - m_arch.GetAddressByteSize(), false, scalar, + m_arch.GetSpec().GetAddressByteSize(), false, scalar, error)) { addr_t pointer_vm_addr = scalar.ULongLong(LLDB_INVALID_ADDRESS); if (pointer_vm_addr != LLDB_INVALID_ADDRESS) { @@ -2212,7 +2362,7 @@ lldb::addr_t Target::GetPersistentSymbol(const ConstString &name) { lldb::addr_t Target::GetCallableLoadAddress(lldb::addr_t load_addr, AddressClass addr_class) const { addr_t code_addr = load_addr; - switch (m_arch.GetMachine()) { + switch (m_arch.GetSpec().GetMachine()) { case llvm::Triple::mips: case llvm::Triple::mipsel: case llvm::Triple::mips64: @@ -2271,7 +2421,7 @@ lldb::addr_t Target::GetCallableLoadAddress(lldb::addr_t load_addr, lldb::addr_t Target::GetOpcodeLoadAddress(lldb::addr_t load_addr, AddressClass addr_class) const { addr_t opcode_addr = load_addr; - switch (m_arch.GetMachine()) { + switch (m_arch.GetSpec().GetMachine()) { case llvm::Triple::mips: case llvm::Triple::mipsel: case llvm::Triple::mips64: @@ -2303,7 +2453,7 @@ lldb::addr_t Target::GetBreakableLoadAddress(lldb::addr_t addr) { addr_t breakable_addr = addr; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - switch (m_arch.GetMachine()) { + switch (m_arch.GetSpec().GetMachine()) { default: break; case llvm::Triple::mips: @@ -2314,7 +2464,7 @@ lldb::addr_t Target::GetBreakableLoadAddress(lldb::addr_t addr) { addr_t current_offset = 0; uint32_t loop_count = 0; Address resolved_addr; - uint32_t arch_flags = m_arch.GetFlags(); + uint32_t arch_flags = m_arch.GetSpec().GetFlags(); bool IsMips16 = arch_flags & ArchSpec::eMIPSAse_mips16; bool IsMicromips = arch_flags & ArchSpec::eMIPSAse_micromips; SectionLoadList §ion_load_list = GetSectionLoadList(); @@ -2367,7 +2517,7 @@ lldb::addr_t Target::GetBreakableLoadAddress(lldb::addr_t addr) { // Create Disassembler Instance lldb::DisassemblerSP disasm_sp( - Disassembler::FindPlugin(m_arch, nullptr, nullptr)); + Disassembler::FindPlugin(m_arch.GetSpec(), nullptr, nullptr)); ExecutionContext exe_ctx; CalculateExecutionContext(exe_ctx); @@ -2529,6 +2679,10 @@ void Target::RunStopHooks() { if (!m_process_sp) return; + + // Somebody might have restarted the process: + if (m_process_sp->GetState() != eStateStopped) + return; // <rdar://problem/12027563> make sure we check that we are not stopped // because of us running a user expression @@ -2634,9 +2788,12 @@ void Target::RunStopHooks() { // running the stop hooks. if ((result.GetStatus() == eReturnStatusSuccessContinuingNoResult) || (result.GetStatus() == eReturnStatusSuccessContinuingResult)) { - result.AppendMessageWithFormat("Aborting stop hooks, hook %" PRIu64 - " set the program running.", - cur_hook_sp->GetID()); + // But only complain if there were more stop hooks to do: + StopHookCollection::iterator tmp = pos; + if (++tmp != end) + result.AppendMessageWithFormat("\nAborting stop hooks, hook %" PRIu64 + " set the program running.\n", + cur_hook_sp->GetID()); keep_going = false; } } @@ -3505,9 +3662,11 @@ static PropertyDefinition g_experimental_properties[]{ "This will fix symbol resolution when there are name collisions between " "ivars and local variables. " "But it can make expressions run much more slowly."}, + {"use-modern-type-lookup", OptionValue::eTypeBoolean, true, false, nullptr, + nullptr, "If true, use Clang's modern type lookup infrastructure."}, {nullptr, OptionValue::eTypeInvalid, true, 0, nullptr, nullptr, nullptr}}; -enum { ePropertyInjectLocalVars = 0 }; +enum { ePropertyInjectLocalVars = 0, ePropertyUseModernTypeLookup }; class TargetExperimentalOptionValueProperties : public OptionValueProperties { public: @@ -3618,6 +3777,18 @@ void TargetProperties::SetInjectLocalVariables(ExecutionContext *exe_ctx, true); } +bool TargetProperties::GetUseModernTypeLookup() const { + const Property *exp_property = m_collection_sp->GetPropertyAtIndex( + nullptr, false, ePropertyExperimental); + OptionValueProperties *exp_values = + exp_property->GetValue()->GetAsProperties(); + if (exp_values) + return exp_values->GetPropertyAtIndexAsBoolean( + nullptr, ePropertyUseModernTypeLookup, true); + else + return true; +} + ArchSpec TargetProperties::GetDefaultArchitecture() const { OptionValueArch *value = m_collection_sp->GetPropertyAtIndexAsOptionValueArch( nullptr, ePropertyDefaultArch); diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp index 505d14012d65b..217cbccedf6e5 100644 --- a/source/Target/Thread.cpp +++ b/source/Target/Thread.cpp @@ -442,10 +442,9 @@ lldb::StopInfoSP Thread::GetPrivateStopInfo() { if (m_stop_info_override_stop_id != process_stop_id) { m_stop_info_override_stop_id = process_stop_id; if (m_stop_info_sp) { - ArchSpec::StopInfoOverrideCallbackType callback = - GetProcess()->GetStopInfoOverrideCallback(); - if (callback) - callback(*this); + if (Architecture *arch = + process_sp->GetTarget().GetArchitecturePlugin()) + arch->OverrideStopInfo(*this); } } } @@ -2075,6 +2074,7 @@ Unwind *Thread::GetUnwinder() { case llvm::Triple::mips64el: case llvm::Triple::ppc: case llvm::Triple::ppc64: + case llvm::Triple::ppc64le: case llvm::Triple::systemz: case llvm::Triple::hexagon: m_unwinder_ap.reset(new UnwindLLDB(*this)); diff --git a/source/Target/ThreadPlanStepInRange.cpp b/source/Target/ThreadPlanStepInRange.cpp index caaaffea8e8ad..6c5a9954f23f4 100644 --- a/source/Target/ThreadPlanStepInRange.cpp +++ b/source/Target/ThreadPlanStepInRange.cpp @@ -191,8 +191,12 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) { if (!m_sub_plan_sp) { // Otherwise check the ShouldStopHere for step out: m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order); - if (log) - log->Printf("ShouldStopHere says we should step out of this frame."); + if (log) { + if (m_sub_plan_sp) + log->Printf("ShouldStopHere found plan to step out of this frame."); + else + log->Printf("ShouldStopHere no plan to step out of this frame."); + } } else if (log) { log->Printf( "Thought I stepped out, but in fact arrived at a trampoline."); diff --git a/source/Target/ThreadPlanTracer.cpp b/source/Target/ThreadPlanTracer.cpp index 014c7fd27975c..5057ca0a711bb 100644 --- a/source/Target/ThreadPlanTracer.cpp +++ b/source/Target/ThreadPlanTracer.cpp @@ -11,9 +11,6 @@ // C++ Includes #include <cstring> -// Other libraries and framework includes -// Project includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/Module.h" diff --git a/source/Target/UnixSignals.cpp b/source/Target/UnixSignals.cpp index a4ec32bd00759..150c6619859ff 100644 --- a/source/Target/UnixSignals.cpp +++ b/source/Target/UnixSignals.cpp @@ -16,8 +16,8 @@ #include "Plugins/Process/Utility/LinuxSignals.h" #include "Plugins/Process/Utility/MipsLinuxSignals.h" #include "Plugins/Process/Utility/NetBSDSignals.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Host/StringConvert.h" +#include "lldb/Utility/ArchSpec.h" using namespace lldb_private; diff --git a/source/Core/ArchSpec.cpp b/source/Utility/ArchSpec.cpp index bfe9750f70f05..a10fe78260bb3 100644 --- a/source/Core/ArchSpec.cpp +++ b/source/Utility/ArchSpec.cpp @@ -7,21 +7,12 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/ArchSpec.h" +#include "lldb/Utility/ArchSpec.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Target/Platform.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Target/Thread.h" #include "lldb/Utility/NameMatches.h" #include "lldb/Utility/Stream.h" // for Stream #include "lldb/Utility/StringList.h" #include "lldb/lldb-defines.h" // for LLDB_INVALID_C... -#include "lldb/lldb-forward.h" // for RegisterContextSP - -#include "Plugins/Process/Utility/ARMDefines.h" -#include "Plugins/Process/Utility/InstructionUtils.h" - #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Twine.h" // for Twine #include "llvm/BinaryFormat/COFF.h" @@ -30,10 +21,6 @@ #include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH #include "llvm/Support/Host.h" -#include <memory> // for shared_ptr -#include <string> -#include <tuple> // for tie, tuple - using namespace lldb; using namespace lldb_private; @@ -188,6 +175,8 @@ static const CoreDefinition g_core_definitions[] = { {eByteOrderBig, 4, 4, 4, llvm::Triple::ppc, ArchSpec::eCore_ppc_ppc970, "ppc970"}, + {eByteOrderLittle, 8, 4, 4, llvm::Triple::ppc64le, + ArchSpec::eCore_ppc64le_generic, "powerpc64le"}, {eByteOrderBig, 8, 4, 4, llvm::Triple::ppc64, ArchSpec::eCore_ppc64_generic, "powerpc64"}, {eByteOrderBig, 8, 4, 4, llvm::Triple::ppc64, @@ -372,6 +361,8 @@ static const ArchDefinitionEntry g_macho_arch_entries[] = { SUBTYPE_MASK}, {ArchSpec::eCore_ppc64_generic, llvm::MachO::CPU_TYPE_POWERPC64, 0, UINT32_MAX, SUBTYPE_MASK}, + {ArchSpec::eCore_ppc64le_generic, llvm::MachO::CPU_TYPE_POWERPC64, CPU_ANY, + UINT32_MAX, SUBTYPE_MASK}, {ArchSpec::eCore_ppc64_ppc970_64, llvm::MachO::CPU_TYPE_POWERPC64, 100, UINT32_MAX, SUBTYPE_MASK}, {ArchSpec::eCore_x86_32_i386, llvm::MachO::CPU_TYPE_I386, 3, UINT32_MAX, @@ -414,6 +405,8 @@ static const ArchDefinitionEntry g_elf_arch_entries[] = { 0xFFFFFFFFu, 0xFFFFFFFFu}, // Intel MCU // FIXME: is this correct? {ArchSpec::eCore_ppc_generic, llvm::ELF::EM_PPC, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu}, // PowerPC + {ArchSpec::eCore_ppc64le_generic, llvm::ELF::EM_PPC64, LLDB_INVALID_CPUTYPE, + 0xFFFFFFFFu, 0xFFFFFFFFu}, // PowerPC64le {ArchSpec::eCore_ppc64_generic, llvm::ELF::EM_PPC64, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu}, // PowerPC64 {ArchSpec::eCore_arm_generic, llvm::ELF::EM_ARM, LLDB_INVALID_CPUTYPE, @@ -461,7 +454,9 @@ static const ArchDefinitionEntry g_elf_arch_entries[] = { }; static const ArchDefinition g_elf_arch_def = { - eArchTypeELF, llvm::array_lengthof(g_elf_arch_entries), g_elf_arch_entries, + eArchTypeELF, + llvm::array_lengthof(g_elf_arch_entries), + g_elf_arch_entries, "elf", }; @@ -483,8 +478,10 @@ static const ArchDefinitionEntry g_coff_arch_entries[] = { }; static const ArchDefinition g_coff_arch_def = { - eArchTypeCOFF, llvm::array_lengthof(g_coff_arch_entries), - g_coff_arch_entries, "pe-coff", + eArchTypeCOFF, + llvm::array_lengthof(g_coff_arch_entries), + g_coff_arch_entries, + "pe-coff", }; //===----------------------------------------------------------------------===// @@ -518,7 +515,7 @@ static const CoreDefinition *FindCoreDefinition(llvm::StringRef name) { } static inline const CoreDefinition *FindCoreDefinition(ArchSpec::Core core) { - if (core >= 0 && core < llvm::array_lengthof(g_core_definitions)) + if (core < llvm::array_lengthof(g_core_definitions)) return &g_core_definitions[core]; return nullptr; } @@ -556,15 +553,6 @@ FindArchDefinitionEntry(const ArchDefinition *def, ArchSpec::Core core) { ArchSpec::ArchSpec() {} -ArchSpec::ArchSpec(const char *triple_cstr, Platform *platform) { - if (triple_cstr) - SetTriple(triple_cstr, platform); -} - -ArchSpec::ArchSpec(llvm::StringRef triple_str, Platform *platform) { - SetTriple(triple_str, platform); -} - ArchSpec::ArchSpec(const char *triple_cstr) { if (triple_cstr) SetTriple(triple_cstr); @@ -874,16 +862,6 @@ bool lldb_private::ParseMachCPUDashSubtypeTriple(llvm::StringRef triple_str, return true; } -bool ArchSpec::SetTriple(const char *triple_cstr) { - llvm::StringRef str(triple_cstr ? triple_cstr : ""); - return SetTriple(str); -} - -bool ArchSpec::SetTriple(const char *triple_cstr, Platform *platform) { - llvm::StringRef str(triple_cstr ? triple_cstr : ""); - return SetTriple(str, platform); -} - bool ArchSpec::SetTriple(llvm::StringRef triple) { if (triple.empty()) { Clear(); @@ -893,87 +871,15 @@ bool ArchSpec::SetTriple(llvm::StringRef triple) { if (ParseMachCPUDashSubtypeTriple(triple, *this)) return true; - if (triple.startswith(LLDB_ARCH_DEFAULT)) { - // Special case for the current host default architectures... - if (triple.equals(LLDB_ARCH_DEFAULT_32BIT)) - *this = HostInfo::GetArchitecture(HostInfo::eArchKind32); - else if (triple.equals(LLDB_ARCH_DEFAULT_64BIT)) - *this = HostInfo::GetArchitecture(HostInfo::eArchKind64); - else if (triple.equals(LLDB_ARCH_DEFAULT)) - *this = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); - } else { - SetTriple(llvm::Triple(llvm::Triple::normalize(triple))); - } + SetTriple(llvm::Triple(llvm::Triple::normalize(triple))); return IsValid(); } -bool ArchSpec::SetTriple(llvm::StringRef triple, Platform *platform) { - if (triple.empty()) { - Clear(); - return false; - } - if (ParseMachCPUDashSubtypeTriple(triple, *this)) - return true; - - if (triple.startswith(LLDB_ARCH_DEFAULT)) { - // Special case for the current host default architectures... - if (triple.equals(LLDB_ARCH_DEFAULT_32BIT)) - *this = HostInfo::GetArchitecture(HostInfo::eArchKind32); - else if (triple.equals(LLDB_ARCH_DEFAULT_64BIT)) - *this = HostInfo::GetArchitecture(HostInfo::eArchKind64); - else if (triple.equals(LLDB_ARCH_DEFAULT)) - *this = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); - return IsValid(); - } - - ArchSpec raw_arch(triple); - - llvm::Triple normalized_triple(llvm::Triple::normalize(triple)); - - const bool os_specified = !normalized_triple.getOSName().empty(); - const bool vendor_specified = !normalized_triple.getVendorName().empty(); - const bool env_specified = !normalized_triple.getEnvironmentName().empty(); - - if (os_specified || vendor_specified || env_specified) { - SetTriple(normalized_triple); - return IsValid(); - } - - // We got an arch only. If there is no platform, fallback to the host system - // for defaults. - if (!platform) { - llvm::Triple host_triple(llvm::sys::getDefaultTargetTriple()); - if (!vendor_specified) - normalized_triple.setVendor(host_triple.getVendor()); - if (!vendor_specified) - normalized_triple.setOS(host_triple.getOS()); - if (!env_specified && host_triple.getEnvironmentName().size()) - normalized_triple.setEnvironment(host_triple.getEnvironment()); - SetTriple(normalized_triple); - return IsValid(); - } - - // If we were given a platform, use the platform's system architecture. If - // this is not available (might not be connected) use the first supported - // architecture. - ArchSpec compatible_arch; - if (!platform->IsCompatibleArchitecture(raw_arch, false, &compatible_arch)) { - *this = raw_arch; - return IsValid(); - } - - if (compatible_arch.IsValid()) { - const llvm::Triple &compatible_triple = compatible_arch.GetTriple(); - if (!vendor_specified) - normalized_triple.setVendor(compatible_triple.getVendor()); - if (!os_specified) - normalized_triple.setOS(compatible_triple.getOS()); - if (!env_specified && compatible_triple.hasEnvironment()) - normalized_triple.setEnvironment(compatible_triple.getEnvironment()); - } - - SetTriple(normalized_triple); - return IsValid(); +bool ArchSpec::ContainsOnlyArch(const llvm::Triple &normalized_triple) { + return !normalized_triple.getArchName().empty() && + normalized_triple.getOSName().empty() && + normalized_triple.getVendorName().empty() && + normalized_triple.getEnvironmentName().empty(); } void ArchSpec::MergeFrom(const ArchSpec &other) { @@ -1002,6 +908,9 @@ void ArchSpec::MergeFrom(const ArchSpec &other) { m_core = other.GetCore(); CoreUpdated(true); } + if (GetFlags() == 0) { + SetFlags(other.GetFlags()); + } } bool ArchSpec::SetArchitecture(ArchitectureType arch_type, uint32_t cpu, @@ -1502,102 +1411,6 @@ bool lldb_private::operator<(const ArchSpec &lhs, const ArchSpec &rhs) { return lhs_core < rhs_core; } -static void StopInfoOverrideCallbackTypeARM(lldb_private::Thread &thread) { - // We need to check if we are stopped in Thumb mode in a IT instruction - // and detect if the condition doesn't pass. If this is the case it means - // we won't actually execute this instruction. If this happens we need to - // clear the stop reason to no thread plans think we are stopped for a - // reason and the plans should keep going. - // - // We do this because when single stepping many ARM processes, debuggers - // often use the BVR/BCR registers that says "stop when the PC is not - // equal to its current value". This method of stepping means we can end - // up stopping on instructions inside an if/then block that wouldn't get - // executed. By fixing this we can stop the debugger from seeming like - // you stepped through both the "if" _and_ the "else" clause when source - // level stepping because the debugger stops regardless due to the BVR/BCR - // triggering a stop. - // - // It also means we can set breakpoints on instructions inside an an - // if/then block and correctly skip them if we use the BKPT instruction. - // The ARM and Thumb BKPT instructions are unconditional even when executed - // in a Thumb IT block. - // - // If your debugger inserts software traps in ARM/Thumb code, it will - // need to use 16 and 32 bit instruction for 16 and 32 bit thumb - // instructions respectively. If your debugger inserts a 16 bit thumb - // trap on top of a 32 bit thumb instruction for an opcode that is inside - // an if/then, it will change the it/then to conditionally execute your - // 16 bit trap and then cause your program to crash if it executes the - // trailing 16 bits (the second half of the 32 bit thumb instruction you - // partially overwrote). - - RegisterContextSP reg_ctx_sp(thread.GetRegisterContext()); - if (reg_ctx_sp) { - const uint32_t cpsr = reg_ctx_sp->GetFlags(0); - if (cpsr != 0) { - // Read the J and T bits to get the ISETSTATE - const uint32_t J = Bit32(cpsr, 24); - const uint32_t T = Bit32(cpsr, 5); - const uint32_t ISETSTATE = J << 1 | T; - if (ISETSTATE == 0) { -// NOTE: I am pretty sure we want to enable the code below -// that detects when we stop on an instruction in ARM mode -// that is conditional and the condition doesn't pass. This -// can happen if you set a breakpoint on an instruction that -// is conditional. We currently will _always_ stop on the -// instruction which is bad. You can also run into this while -// single stepping and you could appear to run code in the "if" -// and in the "else" clause because it would stop at all of the -// conditional instructions in both. -// In such cases, we really don't want to stop at this location. -// I will check with the lldb-dev list first before I enable this. -#if 0 - // ARM mode: check for condition on intsruction - const addr_t pc = reg_ctx_sp->GetPC(); - Status error; - // If we fail to read the opcode we will get UINT64_MAX as the - // result in "opcode" which we can use to detect if we read a - // valid opcode. - const uint64_t opcode = thread.GetProcess()->ReadUnsignedIntegerFromMemory(pc, 4, UINT64_MAX, error); - if (opcode <= UINT32_MAX) - { - const uint32_t condition = Bits32((uint32_t)opcode, 31, 28); - if (!ARMConditionPassed(condition, cpsr)) - { - // We ARE stopped on an ARM instruction whose condition doesn't - // pass so this instruction won't get executed. - // Regardless of why it stopped, we need to clear the stop info - thread.SetStopInfo (StopInfoSP()); - } - } -#endif - } else if (ISETSTATE == 1) { - // Thumb mode - const uint32_t ITSTATE = - Bits32(cpsr, 15, 10) << 2 | Bits32(cpsr, 26, 25); - if (ITSTATE != 0) { - const uint32_t condition = Bits32(ITSTATE, 7, 4); - if (!ARMConditionPassed(condition, cpsr)) { - // We ARE stopped in a Thumb IT instruction on an instruction whose - // condition doesn't pass so this instruction won't get executed. - // Regardless of why it stopped, we need to clear the stop info - thread.SetStopInfo(StopInfoSP()); - } - } - } - } - } -} - -ArchSpec::StopInfoOverrideCallbackType -ArchSpec::GetStopInfoOverrideCallback() const { - const llvm::Triple::ArchType machine = GetMachine(); - if (machine == llvm::Triple::arm) - return StopInfoOverrideCallbackTypeARM; - return nullptr; -} - bool ArchSpec::IsFullySpecifiedTriple() const { const auto &user_specified_triple = GetTriple(); @@ -1619,7 +1432,7 @@ bool ArchSpec::IsFullySpecifiedTriple() const { void ArchSpec::PiecewiseTripleCompare( const ArchSpec &other, bool &arch_different, bool &vendor_different, - bool &os_different, bool &os_version_different, bool &env_different) { + bool &os_different, bool &os_version_different, bool &env_different) const { const llvm::Triple &me(GetTriple()); const llvm::Triple &them(other.GetTriple()); diff --git a/source/Utility/CMakeLists.txt b/source/Utility/CMakeLists.txt index 78598562692bb..1a0fb6f86c574 100644 --- a/source/Utility/CMakeLists.txt +++ b/source/Utility/CMakeLists.txt @@ -1,4 +1,46 @@ +set(LLDB_SYSTEM_LIBS) + +# Windows-only libraries +if ( CMAKE_SYSTEM_NAME MATCHES "Windows" ) + list(APPEND LLDB_SYSTEM_LIBS + ws2_32 + rpcrt4 + ) +endif () + +if (NOT LLDB_DISABLE_LIBEDIT) + list(APPEND LLDB_SYSTEM_LIBS edit) +endif() +if (NOT LLDB_DISABLE_CURSES) + list(APPEND LLDB_SYSTEM_LIBS ${CURSES_LIBRARIES}) + if(LLVM_ENABLE_TERMINFO AND HAVE_TERMINFO) + list(APPEND LLDB_SYSTEM_LIBS ${TERMINFO_LIBS}) + endif() +endif() + +if (NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB ) + list(APPEND LLDB_SYSTEM_LIBS atomic) +endif() + +list(APPEND LLDB_SYSTEM_LIBS ${Backtrace_LIBRARY}) + +if (NOT LLDB_DISABLE_PYTHON AND NOT LLVM_BUILD_STATIC) + list(APPEND LLDB_SYSTEM_LIBS ${PYTHON_LIBRARIES}) +endif() + +list(APPEND LLDB_SYSTEM_LIBS ${system_libs}) + +if (LLVM_BUILD_STATIC) + if (NOT LLDB_DISABLE_PYTHON) + list(APPEND LLDB_SYSTEM_LIBS python2.7 util) + endif() + if (NOT LLDB_DISABLE_CURSES) + list(APPEND LLDB_SYSTEM_LIBS gpm) + endif() +endif() + add_lldb_library(lldbUtility + ArchSpec.cpp Baton.cpp Connection.cpp ConstString.cpp @@ -29,7 +71,6 @@ add_lldb_library(lldbUtility StringLexer.cpp StringList.cpp StructuredData.cpp - TaskPool.cpp TildeExpressionResolver.cpp Timer.cpp UserID.cpp @@ -39,7 +80,8 @@ add_lldb_library(lldbUtility VMRange.cpp LINK_LIBS - # lldbUtility cannot have any dependencies + ${LLDB_SYSTEM_LIBS} + # lldbUtility does not depend on other LLDB libraries LINK_COMPONENTS BinaryFormat diff --git a/source/Utility/DataEncoder.cpp b/source/Utility/DataEncoder.cpp index f7ce46889d2f4..433a15bc95230 100644 --- a/source/Utility/DataEncoder.cpp +++ b/source/Utility/DataEncoder.cpp @@ -12,6 +12,7 @@ #include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/Endian.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" // for llvm_unreachable #include "llvm/Support/MathExtras.h" @@ -22,36 +23,7 @@ using namespace lldb; using namespace lldb_private; - -static inline void WriteInt16(unsigned char *ptr, unsigned offset, - uint16_t value) { - *(uint16_t *)(ptr + offset) = value; -} - -static inline void WriteInt32(unsigned char *ptr, unsigned offset, - uint32_t value) { - *(uint32_t *)(ptr + offset) = value; -} - -static inline void WriteInt64(unsigned char *ptr, unsigned offset, - uint64_t value) { - *(uint64_t *)(ptr + offset) = value; -} - -static inline void WriteSwappedInt16(unsigned char *ptr, unsigned offset, - uint16_t value) { - *(uint16_t *)(ptr + offset) = llvm::ByteSwap_16(value); -} - -static inline void WriteSwappedInt32(unsigned char *ptr, unsigned offset, - uint32_t value) { - *(uint32_t *)(ptr + offset) = llvm::ByteSwap_32(value); -} - -static inline void WriteSwappedInt64(unsigned char *ptr, unsigned offset, - uint64_t value) { - *(uint64_t *)(ptr + offset) = llvm::ByteSwap_64(value); -} +using namespace llvm::support::endian; //---------------------------------------------------------------------- // Default constructor. @@ -202,9 +174,9 @@ uint32_t DataEncoder::PutU8(uint32_t offset, uint8_t value) { uint32_t DataEncoder::PutU16(uint32_t offset, uint16_t value) { if (ValidOffsetForDataOfSize(offset, sizeof(value))) { if (m_byte_order != endian::InlHostByteOrder()) - WriteSwappedInt16(m_start, offset, value); + write16be(m_start + offset, value); else - WriteInt16(m_start, offset, value); + write16le(m_start + offset, value); return offset + sizeof(value); } @@ -214,9 +186,9 @@ uint32_t DataEncoder::PutU16(uint32_t offset, uint16_t value) { uint32_t DataEncoder::PutU32(uint32_t offset, uint32_t value) { if (ValidOffsetForDataOfSize(offset, sizeof(value))) { if (m_byte_order != endian::InlHostByteOrder()) - WriteSwappedInt32(m_start, offset, value); + write32be(m_start + offset, value); else - WriteInt32(m_start, offset, value); + write32le(m_start + offset, value); return offset + sizeof(value); } @@ -226,9 +198,9 @@ uint32_t DataEncoder::PutU32(uint32_t offset, uint32_t value) { uint32_t DataEncoder::PutU64(uint32_t offset, uint64_t value) { if (ValidOffsetForDataOfSize(offset, sizeof(value))) { if (m_byte_order != endian::InlHostByteOrder()) - WriteSwappedInt64(m_start, offset, value); + write64be(m_start + offset, value); else - WriteInt64(m_start, offset, value); + write64le(m_start + offset, value); return offset + sizeof(value); } diff --git a/source/Utility/DataExtractor.cpp b/source/Utility/DataExtractor.cpp index 008aff220945b..84c5f81915212 100644 --- a/source/Utility/DataExtractor.cpp +++ b/source/Utility/DataExtractor.cpp @@ -17,6 +17,7 @@ #include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/Endian.h" +#include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StreamString.h" @@ -105,6 +106,20 @@ static inline uint64_t ReadSwapInt64(const void *ptr) { return llvm::ByteSwap_64(value); } +static inline uint64_t ReadMaxInt64(const uint8_t *data, size_t byte_size, + ByteOrder byte_order) { + uint64_t res = 0; + if (byte_order == eByteOrderBig) + for (size_t i = 0; i < byte_size; ++i) + res = (res << 8) | data[i]; + else { + assert(byte_order == eByteOrderLittle); + for (size_t i = 0; i < byte_size; ++i) + res = (res << 8) | data[byte_size - 1 - i]; + } + return res; +} + DataExtractor::DataExtractor() : m_start(nullptr), m_end(nullptr), m_byte_order(endian::InlHostByteOrder()), m_addr_size(sizeof(void *)), @@ -551,107 +566,59 @@ void *DataExtractor::GetU64(offset_t *offset_ptr, void *void_dst, return nullptr; } -//---------------------------------------------------------------------- -// Extract a single integer value from the data and update the offset -// pointed to by "offset_ptr". The size of the extracted integer -// is specified by the "byte_size" argument. "byte_size" should have -// a value between 1 and 4 since the return value is only 32 bits -// wide. Any "byte_size" values less than 1 or greater than 4 will -// result in nothing being extracted, and zero being returned. -// -// RETURNS the integer value that was extracted, or zero on failure. -//---------------------------------------------------------------------- uint32_t DataExtractor::GetMaxU32(offset_t *offset_ptr, size_t byte_size) const { - switch (byte_size) { - case 1: - return GetU8(offset_ptr); - break; - case 2: - return GetU16(offset_ptr); - break; - case 4: - return GetU32(offset_ptr); - break; - default: - assert(false && "GetMaxU32 unhandled case!"); - break; - } - return 0; + lldbassert(byte_size > 0 && byte_size <= 4 && "GetMaxU32 invalid byte_size!"); + return GetMaxU64(offset_ptr, byte_size); } -//---------------------------------------------------------------------- -// Extract a single integer value from the data and update the offset -// pointed to by "offset_ptr". The size of the extracted integer -// is specified by the "byte_size" argument. "byte_size" should have -// a value >= 1 and <= 8 since the return value is only 64 bits -// wide. Any "byte_size" values less than 1 or greater than 8 will -// result in nothing being extracted, and zero being returned. -// -// RETURNS the integer value that was extracted, or zero on failure. -//---------------------------------------------------------------------- -uint64_t DataExtractor::GetMaxU64(offset_t *offset_ptr, size_t size) const { - switch (size) { +uint64_t DataExtractor::GetMaxU64(offset_t *offset_ptr, + size_t byte_size) const { + lldbassert(byte_size > 0 && byte_size <= 8 && "GetMaxU64 invalid byte_size!"); + switch (byte_size) { case 1: return GetU8(offset_ptr); - break; case 2: return GetU16(offset_ptr); - break; case 4: return GetU32(offset_ptr); - break; case 8: return GetU64(offset_ptr); - break; - default: - assert(false && "GetMax64 unhandled case!"); - break; + default: { + // General case. + const uint8_t *data = + static_cast<const uint8_t *>(GetData(offset_ptr, byte_size)); + if (data == nullptr) + return 0; + return ReadMaxInt64(data, byte_size, m_byte_order); + } } return 0; } uint64_t DataExtractor::GetMaxU64_unchecked(offset_t *offset_ptr, - size_t size) const { - switch (size) { + size_t byte_size) const { + switch (byte_size) { case 1: return GetU8_unchecked(offset_ptr); - break; case 2: return GetU16_unchecked(offset_ptr); - break; case 4: return GetU32_unchecked(offset_ptr); - break; case 8: return GetU64_unchecked(offset_ptr); - break; - default: - assert(false && "GetMax64 unhandled case!"); - break; + default: { + uint64_t res = ReadMaxInt64(&m_start[*offset_ptr], byte_size, m_byte_order); + *offset_ptr += byte_size; + return res; + } } return 0; } -int64_t DataExtractor::GetMaxS64(offset_t *offset_ptr, size_t size) const { - switch (size) { - case 1: - return (int8_t)GetU8(offset_ptr); - break; - case 2: - return (int16_t)GetU16(offset_ptr); - break; - case 4: - return (int32_t)GetU32(offset_ptr); - break; - case 8: - return (int64_t)GetU64(offset_ptr); - break; - default: - assert(false && "GetMax64 unhandled case!"); - break; - } - return 0; +int64_t DataExtractor::GetMaxS64(offset_t *offset_ptr, size_t byte_size) const { + uint64_t u64 = GetMaxU64(offset_ptr, byte_size); + return llvm::SignExtend64(u64, 8 * byte_size); } uint64_t DataExtractor::GetMaxU64Bitfield(offset_t *offset_ptr, size_t size, diff --git a/source/Utility/FileSpec.cpp b/source/Utility/FileSpec.cpp index 3c4e3407ddf65..72f86917b813b 100644 --- a/source/Utility/FileSpec.cpp +++ b/source/Utility/FileSpec.cpp @@ -700,18 +700,18 @@ void FileSpec::EnumerateDirectory(llvm::StringRef dir_path, fs::recursive_directory_iterator End; for (; Iter != End && !EC; Iter.increment(EC)) { const auto &Item = *Iter; - fs::file_status Status; - if ((EC = Item.status(Status))) + llvm::ErrorOr<fs::basic_file_status> Status = Item.status(); + if (!Status) break; - if (!find_files && fs::is_regular_file(Status)) + if (!find_files && fs::is_regular_file(*Status)) continue; - if (!find_directories && fs::is_directory(Status)) + if (!find_directories && fs::is_directory(*Status)) continue; - if (!find_other && fs::is_other(Status)) + if (!find_other && fs::is_other(*Status)) continue; FileSpec Spec(Item.path(), false); - auto Result = callback(callback_baton, Status.type(), Spec); + auto Result = callback(callback_baton, Status->type(), Spec); if (Result == eEnumerateDirectoryResultQuit) return; if (Result == eEnumerateDirectoryResultNext) { diff --git a/source/Utility/JSON.cpp b/source/Utility/JSON.cpp index 1520bc7c47ec7..9049f596ab9a5 100644 --- a/source/Utility/JSON.cpp +++ b/source/Utility/JSON.cpp @@ -22,7 +22,7 @@ using namespace lldb_private; std::string JSONString::json_string_quote_metachars(const std::string &s) { - if (s.find('"') == std::string::npos) + if (s.find_first_of("\\\n\"") == std::string::npos) return s; std::string output; @@ -30,8 +30,9 @@ std::string JSONString::json_string_quote_metachars(const std::string &s) { const char *s_chars = s.c_str(); for (size_t i = 0; i < s_size; i++) { unsigned char ch = *(s_chars + i); - if (ch == '"') { + if (ch == '"' || ch == '\\' || ch == '\n') { output.push_back('\\'); + if (ch == '\n') ch = 'n'; } output.push_back(ch); } diff --git a/source/Utility/Log.cpp b/source/Utility/Log.cpp index a80b106838bc5..f247124f8d632 100644 --- a/source/Utility/Log.cpp +++ b/source/Utility/Log.cpp @@ -32,6 +32,7 @@ #include <process.h> // for getpid #else #include <unistd.h> +#include <pthread.h> #endif using namespace lldb_private; @@ -181,6 +182,13 @@ void Log::Warning(const char *format, ...) { Printf("warning: %s", Content.c_str()); } +void Log::Initialize() { +#ifdef LLVM_ON_UNIX + pthread_atfork(nullptr, nullptr, &Log::DisableLoggingChild); +#endif + InitializeLldbChannel(); +} + void Log::Register(llvm::StringRef name, Channel &channel) { auto iter = g_channel_map->try_emplace(name, channel); assert(iter.second == true); @@ -279,8 +287,7 @@ void Log::WriteHeader(llvm::raw_ostream &OS, llvm::StringRef file, if (options.Test(LLDB_LOG_OPTION_PREPEND_THREAD_NAME)) { llvm::SmallString<32> thread_name; llvm::get_thread_name(thread_name); - if (!thread_name.empty()) - OS << thread_name; + OS << llvm::formatv("{0,-16} ", thread_name); } if (options.Test(LLDB_LOG_OPTION_BACKTRACE)) @@ -321,3 +328,11 @@ void Log::Format(llvm::StringRef file, llvm::StringRef function, message << payload << "\n"; WriteMessage(message.str()); } + +void Log::DisableLoggingChild() { + // Disable logging by clearing out the atomic variable after forking -- if we + // forked while another thread held the channel mutex, we would deadlock when + // trying to write to the log. + for (auto &c: *g_channel_map) + c.second.m_channel.log_ptr.store(nullptr, std::memory_order_relaxed); +} diff --git a/source/Utility/Logging.cpp b/source/Utility/Logging.cpp index 0bd6d6692e37d..c9a6ef1bd1eae 100644 --- a/source/Utility/Logging.cpp +++ b/source/Utility/Logging.cpp @@ -51,7 +51,7 @@ static constexpr Log::Category g_categories[] = { static Log::Channel g_log_channel(g_categories, LIBLLDB_LOG_DEFAULT); -void lldb_private::InitializeLog() { +void lldb_private::InitializeLldbChannel() { Log::Register("lldb", g_log_channel); } diff --git a/source/Utility/PPC64LE_DWARF_Registers.h b/source/Utility/PPC64LE_DWARF_Registers.h new file mode 100644 index 0000000000000..1a7503790e5da --- /dev/null +++ b/source/Utility/PPC64LE_DWARF_Registers.h @@ -0,0 +1,194 @@ +//===-- PPC64LE_DWARF_Registers.h -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_PPC64LE_DWARF_Registers_h_ +#define utility_PPC64LE_DWARF_Registers_h_ + +#include "lldb/lldb-private.h" + +namespace ppc64le_dwarf { + +enum { + dwarf_r0_ppc64le = 0, + dwarf_r1_ppc64le, + dwarf_r2_ppc64le, + dwarf_r3_ppc64le, + dwarf_r4_ppc64le, + dwarf_r5_ppc64le, + dwarf_r6_ppc64le, + dwarf_r7_ppc64le, + dwarf_r8_ppc64le, + dwarf_r9_ppc64le, + dwarf_r10_ppc64le, + dwarf_r11_ppc64le, + dwarf_r12_ppc64le, + dwarf_r13_ppc64le, + dwarf_r14_ppc64le, + dwarf_r15_ppc64le, + dwarf_r16_ppc64le, + dwarf_r17_ppc64le, + dwarf_r18_ppc64le, + dwarf_r19_ppc64le, + dwarf_r20_ppc64le, + dwarf_r21_ppc64le, + dwarf_r22_ppc64le, + dwarf_r23_ppc64le, + dwarf_r24_ppc64le, + dwarf_r25_ppc64le, + dwarf_r26_ppc64le, + dwarf_r27_ppc64le, + dwarf_r28_ppc64le, + dwarf_r29_ppc64le, + dwarf_r30_ppc64le, + dwarf_r31_ppc64le, + dwarf_f0_ppc64le, + dwarf_f1_ppc64le, + dwarf_f2_ppc64le, + dwarf_f3_ppc64le, + dwarf_f4_ppc64le, + dwarf_f5_ppc64le, + dwarf_f6_ppc64le, + dwarf_f7_ppc64le, + dwarf_f8_ppc64le, + dwarf_f9_ppc64le, + dwarf_f10_ppc64le, + dwarf_f11_ppc64le, + dwarf_f12_ppc64le, + dwarf_f13_ppc64le, + dwarf_f14_ppc64le, + dwarf_f15_ppc64le, + dwarf_f16_ppc64le, + dwarf_f17_ppc64le, + dwarf_f18_ppc64le, + dwarf_f19_ppc64le, + dwarf_f20_ppc64le, + dwarf_f21_ppc64le, + dwarf_f22_ppc64le, + dwarf_f23_ppc64le, + dwarf_f24_ppc64le, + dwarf_f25_ppc64le, + dwarf_f26_ppc64le, + dwarf_f27_ppc64le, + dwarf_f28_ppc64le, + dwarf_f29_ppc64le, + dwarf_f30_ppc64le, + dwarf_f31_ppc64le, + dwarf_lr_ppc64le = 65, + dwarf_ctr_ppc64le, + dwarf_cr_ppc64le = 68, + dwarf_xer_ppc64le = 76, + dwarf_vr0_ppc64le, + dwarf_vr1_ppc64le, + dwarf_vr2_ppc64le, + dwarf_vr3_ppc64le, + dwarf_vr4_ppc64le, + dwarf_vr5_ppc64le, + dwarf_vr6_ppc64le, + dwarf_vr7_ppc64le, + dwarf_vr8_ppc64le, + dwarf_vr9_ppc64le, + dwarf_vr10_ppc64le, + dwarf_vr11_ppc64le, + dwarf_vr12_ppc64le, + dwarf_vr13_ppc64le, + dwarf_vr14_ppc64le, + dwarf_vr15_ppc64le, + dwarf_vr16_ppc64le, + dwarf_vr17_ppc64le, + dwarf_vr18_ppc64le, + dwarf_vr19_ppc64le, + dwarf_vr20_ppc64le, + dwarf_vr21_ppc64le, + dwarf_vr22_ppc64le, + dwarf_vr23_ppc64le, + dwarf_vr24_ppc64le, + dwarf_vr25_ppc64le, + dwarf_vr26_ppc64le, + dwarf_vr27_ppc64le, + dwarf_vr28_ppc64le, + dwarf_vr29_ppc64le, + dwarf_vr30_ppc64le, + dwarf_vr31_ppc64le, + dwarf_vscr_ppc64le = 110, + dwarf_vrsave_ppc64le = 117, + dwarf_pc_ppc64le, + dwarf_softe_ppc64le, + dwarf_trap_ppc64le, + dwarf_origr3_ppc64le, + dwarf_fpscr_ppc64le, + dwarf_msr_ppc64le, + dwarf_vs0_ppc64le, + dwarf_vs1_ppc64le, + dwarf_vs2_ppc64le, + dwarf_vs3_ppc64le, + dwarf_vs4_ppc64le, + dwarf_vs5_ppc64le, + dwarf_vs6_ppc64le, + dwarf_vs7_ppc64le, + dwarf_vs8_ppc64le, + dwarf_vs9_ppc64le, + dwarf_vs10_ppc64le, + dwarf_vs11_ppc64le, + dwarf_vs12_ppc64le, + dwarf_vs13_ppc64le, + dwarf_vs14_ppc64le, + dwarf_vs15_ppc64le, + dwarf_vs16_ppc64le, + dwarf_vs17_ppc64le, + dwarf_vs18_ppc64le, + dwarf_vs19_ppc64le, + dwarf_vs20_ppc64le, + dwarf_vs21_ppc64le, + dwarf_vs22_ppc64le, + dwarf_vs23_ppc64le, + dwarf_vs24_ppc64le, + dwarf_vs25_ppc64le, + dwarf_vs26_ppc64le, + dwarf_vs27_ppc64le, + dwarf_vs28_ppc64le, + dwarf_vs29_ppc64le, + dwarf_vs30_ppc64le, + dwarf_vs31_ppc64le, + dwarf_vs32_ppc64le, + dwarf_vs33_ppc64le, + dwarf_vs34_ppc64le, + dwarf_vs35_ppc64le, + dwarf_vs36_ppc64le, + dwarf_vs37_ppc64le, + dwarf_vs38_ppc64le, + dwarf_vs39_ppc64le, + dwarf_vs40_ppc64le, + dwarf_vs41_ppc64le, + dwarf_vs42_ppc64le, + dwarf_vs43_ppc64le, + dwarf_vs44_ppc64le, + dwarf_vs45_ppc64le, + dwarf_vs46_ppc64le, + dwarf_vs47_ppc64le, + dwarf_vs48_ppc64le, + dwarf_vs49_ppc64le, + dwarf_vs50_ppc64le, + dwarf_vs51_ppc64le, + dwarf_vs52_ppc64le, + dwarf_vs53_ppc64le, + dwarf_vs54_ppc64le, + dwarf_vs55_ppc64le, + dwarf_vs56_ppc64le, + dwarf_vs57_ppc64le, + dwarf_vs58_ppc64le, + dwarf_vs59_ppc64le, + dwarf_vs60_ppc64le, + dwarf_vs61_ppc64le, + dwarf_vs62_ppc64le, + dwarf_vs63_ppc64le, +}; + +} // namespace ppc64le_dwarf + +#endif // utility_PPC64LE_DWARF_Registers_h_ diff --git a/source/Utility/PPC64LE_ehframe_Registers.h b/source/Utility/PPC64LE_ehframe_Registers.h new file mode 100644 index 0000000000000..c5763b3047117 --- /dev/null +++ b/source/Utility/PPC64LE_ehframe_Registers.h @@ -0,0 +1,194 @@ +//===-- PPC64LE_ehframe_Registers.h -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_PPC64LE_ehframe_Registers_h_ +#define utility_PPC64LE_ehframe_Registers_h_ + +// The register numbers used in the eh_frame unwind information. +// Should be the same as DWARF register numbers. + +namespace ppc64le_ehframe { + +enum { + r0 = 0, + r1, + r2, + r3, + r4, + r5, + r6, + r7, + r8, + r9, + r10, + r11, + r12, + r13, + r14, + r15, + r16, + r17, + r18, + r19, + r20, + r21, + r22, + r23, + r24, + r25, + r26, + r27, + r28, + r29, + r30, + r31, + f0, + f1, + f2, + f3, + f4, + f5, + f6, + f7, + f8, + f9, + f10, + f11, + f12, + f13, + f14, + f15, + f16, + f17, + f18, + f19, + f20, + f21, + f22, + f23, + f24, + f25, + f26, + f27, + f28, + f29, + f30, + f31, + lr = 65, + ctr, + cr = 68, + xer = 76, + vr0, + vr1, + vr2, + vr3, + vr4, + vr5, + vr6, + vr7, + vr8, + vr9, + vr10, + vr11, + vr12, + vr13, + vr14, + vr15, + vr16, + vr17, + vr18, + vr19, + vr20, + vr21, + vr22, + vr23, + vr24, + vr25, + vr26, + vr27, + vr28, + vr29, + vr30, + vr31, + vscr = 110, + vrsave = 117, + pc, + softe, + trap, + origr3, + fpscr, + msr, + vs0, + vs1, + vs2, + vs3, + vs4, + vs5, + vs6, + vs7, + vs8, + vs9, + vs10, + vs11, + vs12, + vs13, + vs14, + vs15, + vs16, + vs17, + vs18, + vs19, + vs20, + vs21, + vs22, + vs23, + vs24, + vs25, + vs26, + vs27, + vs28, + vs29, + vs30, + vs31, + vs32, + vs33, + vs34, + vs35, + vs36, + vs37, + vs38, + vs39, + vs40, + vs41, + vs42, + vs43, + vs44, + vs45, + vs46, + vs47, + vs48, + vs49, + vs50, + vs51, + vs52, + vs53, + vs54, + vs55, + vs56, + vs57, + vs58, + vs59, + vs60, + vs61, + vs62, + vs63, +}; +} + +#endif // utility_PPC64LE_ehframe_Registers_h_ diff --git a/source/Utility/SelectHelper.cpp b/source/Utility/SelectHelper.cpp index a46213f8bfcb8..200b2ae42759b 100644 --- a/source/Utility/SelectHelper.cpp +++ b/source/Utility/SelectHelper.cpp @@ -32,6 +32,7 @@ #define NOMINMAX #include <winsock2.h> #else +#include <sys/time.h> #include <sys/select.h> #endif diff --git a/source/Utility/Status.cpp b/source/Utility/Status.cpp index b11a3db64e6d2..a6a889a71e548 100644 --- a/source/Utility/Status.cpp +++ b/source/Utility/Status.cpp @@ -104,16 +104,6 @@ const Status &Status::operator=(const Status &rhs) { return *this; } -//---------------------------------------------------------------------- -// Assignment operator -//---------------------------------------------------------------------- -const Status &Status::operator=(uint32_t err) { - m_code = err; - m_type = eErrorTypeMachKernel; - m_string.clear(); - return *this; -} - Status::~Status() = default; //---------------------------------------------------------------------- diff --git a/source/Utility/StringExtractorGDBRemote.cpp b/source/Utility/StringExtractorGDBRemote.cpp index 8e50c0106a487..818347a42a2cb 100644 --- a/source/Utility/StringExtractorGDBRemote.cpp +++ b/source/Utility/StringExtractorGDBRemote.cpp @@ -103,6 +103,7 @@ StringExtractorGDBRemote::GetServerPacketType() const { case 'P': if (PACKET_STARTS_WITH("QPassSignals:")) return eServerPacketType_QPassSignals; + break; case 'S': if (PACKET_MATCHES("QStartNoAckMode")) diff --git a/source/Utility/StructuredData.cpp b/source/Utility/StructuredData.cpp index 9fc05354cfd3f..492fc585ad07f 100644 --- a/source/Utility/StructuredData.cpp +++ b/source/Utility/StructuredData.cpp @@ -15,6 +15,7 @@ #include "lldb/Utility/Stream.h" // for Stream #include "lldb/Utility/StreamString.h" #include "llvm/ADT/STLExtras.h" // for make_unique +#include "llvm/Support/MemoryBuffer.h" #include <cerrno> #include <cstdlib> #include <inttypes.h> diff --git a/source/Utility/UUID.cpp b/source/Utility/UUID.cpp index b47f8b52f1c24..98d4c30cc7f11 100644 --- a/source/Utility/UUID.cpp +++ b/source/Utility/UUID.cpp @@ -21,11 +21,10 @@ namespace lldb_private { -UUID::UUID() : m_num_uuid_bytes(16) { ::memset(m_uuid, 0, sizeof(m_uuid)); } +UUID::UUID() { Clear(); } UUID::UUID(const UUID &rhs) { - m_num_uuid_bytes = rhs.m_num_uuid_bytes; - ::memcpy(m_uuid, rhs.m_uuid, sizeof(m_uuid)); + SetBytes(rhs.m_uuid, rhs.m_num_uuid_bytes); } UUID::UUID(const void *uuid_bytes, uint32_t num_uuid_bytes) { @@ -74,14 +73,7 @@ std::string UUID::GetAsString(const char *separator) const { } void UUID::Dump(Stream *s) const { - const uint8_t *u = (const uint8_t *)GetBytes(); - s->Printf("%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%" - "2.2X%2.2X%2.2X%2.2X", - u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7], u[8], u[9], u[10], - u[11], u[12], u[13], u[14], u[15]); - if (m_num_uuid_bytes == 20) { - s->Printf("-%2.2X%2.2X%2.2X%2.2X", u[16], u[17], u[18], u[19]); - } + s->PutCString(GetAsString().c_str()); } bool UUID::SetBytes(const void *uuid_bytes, uint32_t num_uuid_bytes) { @@ -109,7 +101,7 @@ bool UUID::SetBytes(const void *uuid_bytes, uint32_t num_uuid_bytes) { return false; } -size_t UUID::GetByteSize() { return m_num_uuid_bytes; } +size_t UUID::GetByteSize() const { return m_num_uuid_bytes; } bool UUID::IsValid() const { return m_uuid[0] || m_uuid[1] || m_uuid[2] || m_uuid[3] || m_uuid[4] || @@ -198,8 +190,7 @@ bool lldb_private::operator==(const lldb_private::UUID &lhs, bool lldb_private::operator!=(const lldb_private::UUID &lhs, const lldb_private::UUID &rhs) { - return ::memcmp(lhs.GetBytes(), rhs.GetBytes(), - sizeof(lldb_private::UUID::ValueType)) != 0; + return !(lhs == rhs); } bool lldb_private::operator<(const lldb_private::UUID &lhs, @@ -210,18 +201,15 @@ bool lldb_private::operator<(const lldb_private::UUID &lhs, bool lldb_private::operator<=(const lldb_private::UUID &lhs, const lldb_private::UUID &rhs) { - return ::memcmp(lhs.GetBytes(), rhs.GetBytes(), - sizeof(lldb_private::UUID::ValueType)) <= 0; + return !(lhs > rhs); } bool lldb_private::operator>(const lldb_private::UUID &lhs, const lldb_private::UUID &rhs) { - return ::memcmp(lhs.GetBytes(), rhs.GetBytes(), - sizeof(lldb_private::UUID::ValueType)) > 0; + return rhs < lhs; } bool lldb_private::operator>=(const lldb_private::UUID &lhs, const lldb_private::UUID &rhs) { - return ::memcmp(lhs.GetBytes(), rhs.GetBytes(), - sizeof(lldb_private::UUID::ValueType)) >= 0; + return !(lhs < rhs); } diff --git a/source/Utility/UriParser.cpp b/source/Utility/UriParser.cpp index bb57211af4687..a6d81e7a2c8b8 100644 --- a/source/Utility/UriParser.cpp +++ b/source/Utility/UriParser.cpp @@ -22,7 +22,7 @@ using namespace lldb_private; bool UriParser::Parse(llvm::StringRef uri, llvm::StringRef &scheme, llvm::StringRef &hostname, int &port, llvm::StringRef &path) { - llvm::StringRef tmp_scheme, tmp_hostname, tmp_port, tmp_path; + llvm::StringRef tmp_scheme, tmp_hostname, tmp_path; const llvm::StringRef kSchemeSep("://"); auto pos = uri.find(kSchemeSep); @@ -43,7 +43,7 @@ bool UriParser::Parse(llvm::StringRef uri, llvm::StringRef &scheme, ((path_pos != std::string::npos) ? path_pos : uri.size()) - host_pos); // Extract hostname - if (host_port[0] == '[') { + if (!host_port.empty() && host_port[0] == '[') { // hostname is enclosed with square brackets. pos = host_port.find(']'); if (pos == std::string::npos) diff --git a/source/lldb.cpp b/source/lldb.cpp index efdcef8f0527a..1be0461977700 100644 --- a/source/lldb.cpp +++ b/source/lldb.cpp @@ -15,11 +15,11 @@ using namespace lldb_private; #include "clang/Basic/Version.h" #ifdef HAVE_SVN_VERSION_INC -# include "SVNVersion.inc" +#include "SVNVersion.inc" #endif #ifdef HAVE_APPLE_VERSION_INC -# include "AppleVersion.inc" +#include "AppleVersion.inc" #endif static const char *GetLLDBRevision() { @@ -38,7 +38,6 @@ static const char *GetLLDBRepository() { #endif } - #define QUOTE(str) #str #define EXPAND_AND_QUOTE(str) QUOTE(str) @@ -47,13 +46,9 @@ const char *lldb_private::GetVersion() { // as the clang tool. static std::string g_version_str; if (g_version_str.empty()) { - -#ifdef LLDB_VERSION_STRING - g_version_str += EXPAND_AND_QUOTE(LLDB_VERSION_STRING); -#else g_version_str += "lldb version "; g_version_str += CLANG_VERSION_STRING; -#endif + const char *lldb_repo = GetLLDBRepository(); const char *lldb_rev = GetLLDBRevision(); if (lldb_repo || lldb_rev) { @@ -77,7 +72,6 @@ const char *lldb_private::GetVersion() { g_version_str += "\n llvm revision "; g_version_str += llvm_rev; } - } return g_version_str.c_str(); } |