diff options
| -rw-r--r-- | lldb/include/lldb/Core/RangeMap.h | 27 | ||||
| -rw-r--r-- | lldb/include/lldb/Core/StructuredData.h | 89 | ||||
| -rw-r--r-- | lldb/include/lldb/Target/Memory.h | 17 | ||||
| -rw-r--r-- | lldb/source/API/SBThread.cpp | 4 | ||||
| -rw-r--r-- | lldb/source/Core/StructuredData.cpp | 4 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp | 27 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h | 7 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp | 617 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h | 17 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp | 7 | ||||
| -rw-r--r-- | lldb/source/Target/Memory.cpp | 139 | ||||
| -rw-r--r-- | lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj | 2 | ||||
| -rw-r--r-- | lldb/tools/debugserver/source/JSONGenerator.h | 490 | ||||
| -rw-r--r-- | lldb/tools/debugserver/source/RNBRemote.cpp | 199 | ||||
| -rw-r--r-- | lldb/tools/debugserver/source/RNBRemote.h | 2 |
15 files changed, 279 insertions, 1369 deletions
diff --git a/lldb/include/lldb/Core/RangeMap.h b/lldb/include/lldb/Core/RangeMap.h index d2c43a5d794..d78504c7d28 100644 --- a/lldb/include/lldb/Core/RangeMap.h +++ b/lldb/include/lldb/Core/RangeMap.h @@ -128,10 +128,9 @@ namespace lldb_private { { return Contains(range.GetRangeBase()) && ContainsEndInclusive(range.GetRangeEnd()); } - - // Returns true if the two ranges adjoing or intersect + bool - DoesAdjoinOrIntersect (const Range &rhs) const + Overlap (const Range &rhs) const { const BaseType lhs_base = this->GetRangeBase(); const BaseType rhs_base = rhs.GetRangeBase(); @@ -140,19 +139,7 @@ namespace lldb_private { bool result = (lhs_base <= rhs_end) && (lhs_end >= rhs_base); return result; } - - // Returns true if the two ranges intersect - bool - DoesIntersect (const Range &rhs) const - { - const BaseType lhs_base = this->GetRangeBase(); - const BaseType rhs_base = rhs.GetRangeBase(); - const BaseType lhs_end = this->GetRangeEnd(); - const BaseType rhs_end = rhs.GetRangeEnd(); - bool result = (lhs_base < rhs_end) && (lhs_end > rhs_base); - return result; - } - + bool operator < (const Range &rhs) const { @@ -254,7 +241,7 @@ namespace lldb_private { // don't end up allocating and making a new collection for no reason for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) { - if (prev != end && prev->DoesAdjoinOrIntersect(*pos)) + if (prev != end && prev->Overlap(*pos)) { can_combine = true; break; @@ -268,7 +255,7 @@ namespace lldb_private { Collection minimal_ranges; for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) { - if (prev != end && prev->DoesAdjoinOrIntersect(*pos)) + if (prev != end && prev->Overlap(*pos)) minimal_ranges.back().SetRangeEnd (std::max<BaseType>(prev->GetRangeEnd(), pos->GetRangeEnd())); else minimal_ranges.push_back (*pos); @@ -534,7 +521,7 @@ namespace lldb_private { // don't end up allocating and making a new collection for no reason for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) { - if (prev != end && prev->DoesAdjoinOrIntersect(*pos)) + if (prev != end && prev->Overlap(*pos)) { can_combine = true; break; @@ -548,7 +535,7 @@ namespace lldb_private { Collection minimal_ranges; for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) { - if (prev != end && prev->DoesAdjoinOrIntersect(*pos)) + if (prev != end && prev->Overlap(*pos)) minimal_ranges.back().SetRangeEnd (std::max<BaseType>(prev->GetRangeEnd(), pos->GetRangeEnd())); else minimal_ranges.push_back (*pos); diff --git a/lldb/include/lldb/Core/StructuredData.h b/lldb/include/lldb/Core/StructuredData.h index 8acfa310dea..9a54fb3429b 100644 --- a/lldb/include/lldb/Core/StructuredData.h +++ b/lldb/include/lldb/Core/StructuredData.h @@ -13,11 +13,10 @@ // C Includes // C++ Includes -#include <functional> #include <map> -#include <string> #include <utility> #include <vector> +#include <string> #include "llvm/ADT/StringRef.h" @@ -141,15 +140,6 @@ public: return NULL; } - uint64_t - GetIntegerValue (uint64_t fail_value = 0) - { - Integer *integer = GetAsInteger (); - if (integer) - return integer->GetValue(); - return fail_value; - } - Float * GetAsFloat () { @@ -158,15 +148,6 @@ public: return NULL; } - double - GetFloatValue (double fail_value = 0.0) - { - Float *f = GetAsFloat (); - if (f) - return f->GetValue(); - return fail_value; - } - Boolean * GetAsBoolean () { @@ -175,15 +156,6 @@ public: return NULL; } - bool - GetBooleanValue (bool fail_value = false) - { - Boolean *b = GetAsBoolean (); - if (b) - return b->GetValue(); - return fail_value; - } - String * GetAsString () { @@ -192,19 +164,6 @@ public: return NULL; } - std::string - GetStringValue(const char *fail_value = NULL) - { - String *s = GetAsString (); - if (s) - return s->GetValue(); - - if (fail_value && fail_value[0]) - return std::string(fail_value); - - return std::string(); - } - Generic * GetAsGeneric() { @@ -238,17 +197,6 @@ public: { } - void - ForEach (std::function <bool(Object* object)> const &foreach_callback) const - { - for (const auto &object_sp : m_items) - { - if (foreach_callback(object_sp.get()) == false) - break; - } - } - - size_t GetSize() const { @@ -499,7 +447,7 @@ public: m_value = string; } - const std::string & + std::string GetValue () { return m_value; @@ -514,7 +462,6 @@ public: class Dictionary : public Object { public: - Dictionary () : Object (Type::eTypeDictionary), m_dict () @@ -531,16 +478,6 @@ public: return m_dict.size(); } - void - ForEach (std::function <bool(ConstString key, Object* object)> const &callback) const - { - for (const auto &pair : m_dict) - { - if (callback (pair.first, pair.second.get()) == false) - break; - } - } - ObjectSP GetKeys() const { @@ -691,25 +628,33 @@ public: void AddIntegerItem (llvm::StringRef key, uint64_t value) { - AddItem (key, ObjectSP (new Integer(value))); + ObjectSP val_obj (new Integer()); + val_obj->GetAsInteger()->SetValue (value); + AddItem (key, val_obj); } void AddFloatItem (llvm::StringRef key, double value) { - AddItem (key, ObjectSP (new Float(value))); + ObjectSP val_obj (new Float()); + val_obj->GetAsFloat()->SetValue (value); + AddItem (key, val_obj); } void AddStringItem (llvm::StringRef key, std::string value) { - AddItem (key, ObjectSP (new String(std::move(value)))); + ObjectSP val_obj (new String()); + val_obj->GetAsString()->SetValue (value); + AddItem (key, val_obj); } void AddBooleanItem (llvm::StringRef key, bool value) { - AddItem (key, ObjectSP (new Boolean(value))); + ObjectSP val_obj (new Boolean()); + val_obj->GetAsBoolean()->SetValue (value); + AddItem (key, val_obj); } void Dump(Stream &s) const override; @@ -745,9 +690,9 @@ public: class Generic : public Object { public: - explicit Generic(void *object = nullptr) : - Object (Type::eTypeGeneric), - m_object (object) + explicit Generic(void *object = nullptr) + : Object(Type::eTypeGeneric) + , m_object(object) { } diff --git a/lldb/include/lldb/Target/Memory.h b/lldb/include/lldb/Target/Memory.h index bf1cc187878..568bbcdf2f7 100644 --- a/lldb/include/lldb/Target/Memory.h +++ b/lldb/include/lldb/Target/Memory.h @@ -52,7 +52,7 @@ namespace lldb_private { uint32_t GetMemoryCacheLineSize() const { - return m_L2_cache_line_byte_size ; + return m_cache_line_byte_size ; } void @@ -61,26 +61,17 @@ namespace lldb_private { bool RemoveInvalidRange (lldb::addr_t base_addr, lldb::addr_t byte_size); - // Allow external sources to populate data into the L1 memory cache - void - AddL1CacheData(lldb::addr_t addr, const void *src, size_t src_len); - - void - AddL1CacheData(lldb::addr_t addr, const lldb::DataBufferSP &data_buffer_sp); - protected: typedef std::map<lldb::addr_t, lldb::DataBufferSP> BlockMap; typedef RangeArray<lldb::addr_t, lldb::addr_t, 4> InvalidRanges; - typedef Range<lldb::addr_t, lldb::addr_t> AddrRange; //------------------------------------------------------------------ // Classes that inherit from MemoryCache can see and modify these //------------------------------------------------------------------ + Process &m_process; + uint32_t m_cache_line_byte_size; Mutex m_mutex; - BlockMap m_L1_cache; // A first level memory cache whose chunk sizes vary that will be used only if the memory read fits entirely in a chunk - BlockMap m_L2_cache; // A memory cache of fixed size chinks (m_L2_cache_line_byte_size bytes in size each) + BlockMap m_cache; InvalidRanges m_invalid_ranges; - Process &m_process; - uint32_t m_L2_cache_line_byte_size; private: DISALLOW_COPY_AND_ASSIGN (MemoryCache); }; diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp index dfc7ce9629f..78f57f52102 100644 --- a/lldb/source/API/SBThread.cpp +++ b/lldb/source/API/SBThread.cpp @@ -114,13 +114,13 @@ SBThread::GetQueue () const else { if (log) - log->Printf ("SBThread(%p)::GetQueue() => error: process is running", + log->Printf ("SBThread(%p)::GetQueueKind() => error: process is running", static_cast<void*>(exe_ctx.GetThreadPtr())); } } if (log) - log->Printf ("SBThread(%p)::GetQueue () => SBQueue(%p)", + log->Printf ("SBThread(%p)::GetQueueKind () => SBQueue(%p)", static_cast<void*>(exe_ctx.GetThreadPtr()), static_cast<void*>(queue_sp.get())); return sb_queue; diff --git a/lldb/source/Core/StructuredData.cpp b/lldb/source/Core/StructuredData.cpp index a2c440948af..9286c3a2991 100644 --- a/lldb/source/Core/StructuredData.cpp +++ b/lldb/source/Core/StructuredData.cpp @@ -298,10 +298,6 @@ StructuredData::ParseJSON (std::string json_text) { object_sp = read_json_object (&c); } - else if (*c == '[') - { - object_sp = read_json_array (&c); - } else { // We have bad characters here, this is likely an illegal JSON string. diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 95eebe66223..d2a15b3152e 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -98,7 +98,6 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() : m_supports_z4 (true), m_supports_QEnvironment (true), m_supports_QEnvironmentHexEncoded (true), - m_supports_jThreadsInfo (true), m_curr_pid (LLDB_INVALID_PROCESS_ID), m_curr_tid (LLDB_INVALID_THREAD_ID), m_curr_tid_run (LLDB_INVALID_THREAD_ID), @@ -602,32 +601,6 @@ GDBRemoteCommunicationClient::GetpPacketSupported (lldb::tid_t tid) return m_supports_p; } -StructuredData::ObjectSP -GDBRemoteCommunicationClient::GetThreadsInfo() -{ - // Get information on all threads at one using the "jThreadsInfo" packet - StructuredData::ObjectSP object_sp; - - if (m_supports_jThreadsInfo) - { - StringExtractorGDBRemote response; - m_supports_jThreadExtendedInfo = eLazyBoolNo; - if (SendPacketAndWaitForResponse("jThreadsInfo", response, false) == PacketResult::Success) - { - if (response.IsUnsupportedResponse()) - { - m_supports_jThreadsInfo = false; - } - else if (!response.Empty()) - { - object_sp = StructuredData::ParseJSON (response.GetStringRef()); - } - } - } - return object_sp; -} - - bool GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported () { diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index b9cea5f3c67..ba34a313090 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -17,7 +17,6 @@ // Other libraries and framework includes // Project includes #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/StructuredData.h" #include "lldb/Target/Process.h" #include "GDBRemoteCommunication.h" @@ -538,9 +537,6 @@ public: bool AvoidGPackets(ProcessGDBRemote *process); - StructuredData::ObjectSP - GetThreadsInfo(); - bool GetThreadExtendedInfoSupported(); @@ -619,8 +615,7 @@ protected: m_supports_z3:1, m_supports_z4:1, m_supports_QEnvironment:1, - m_supports_QEnvironmentHexEncoded:1, - m_supports_jThreadsInfo:1; + m_supports_QEnvironmentHexEncoded:1; lldb::pid_t m_curr_pid; lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all other operations diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index d50ec0e2384..64972dfda36 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -378,7 +378,6 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) : m_async_broadcaster (NULL, "lldb.process.gdb-remote.async-broadcaster"), m_async_thread_state_mutex(Mutex::eMutexTypeRecursive), m_thread_ids (), - m_threads_info_sp (), m_continue_c_tids (), m_continue_C_tids (), m_continue_s_tids (), @@ -1785,356 +1784,6 @@ ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new return true; } -bool -ProcessGDBRemote::CalculateThreadStopInfo (ThreadGDBRemote *thread) -{ - // See if we got thread stop infos for all threads via the "jThreadsInfo" packet - if (m_threads_info_sp) - { - StructuredData::Array *thread_infos = m_threads_info_sp->GetAsArray(); - if (thread_infos) - { - lldb::tid_t tid; - const size_t n = thread_infos->GetSize(); - for (size_t i=0; i<n; ++i) - { - StructuredData::Dictionary *thread_dict = thread_infos->GetItemAtIndex(i)->GetAsDictionary(); - if (thread_dict) - { - if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>("tid", tid, LLDB_INVALID_THREAD_ID)) - { - if (tid == thread->GetID()) - return SetThreadStopInfo(thread_dict); - } - } - } - } - } - - // Fall back to using the qThreadStopInfo packet - StringExtractorGDBRemote stop_packet; - if (GetGDBRemote().GetThreadStopInfo(thread->GetProtocolID(), stop_packet)) - return SetThreadStopInfo (stop_packet) == eStateStopped; - return false; -} - - -ThreadSP -ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid, - uint8_t signo, - const std::string &thread_name, - const std::string &reason, - const std::string &description, - uint32_t exc_type, - const std::vector<addr_t> &exc_data, - addr_t thread_dispatch_qaddr) -{ - ThreadSP thread_sp; - if (tid != LLDB_INVALID_THREAD_ID) - { - // Scope for "locker" below - { - // m_thread_list_real does have its own mutex, but we need to - // hold onto the mutex between the call to m_thread_list_real.FindThreadByID(...) - // and the m_thread_list_real.AddThread(...) so it doesn't change on us - Mutex::Locker locker (m_thread_list_real.GetMutex ()); - thread_sp = m_thread_list_real.FindThreadByProtocolID(tid, false); - - if (!thread_sp) - { - // Create the thread if we need to - thread_sp.reset (new ThreadGDBRemote (*this, tid)); - m_thread_list_real.AddThread(thread_sp); - } - } - - if (thread_sp) - { - ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get()); - - // Clear the stop info just in case we don't set it to anything - thread_sp->SetStopInfo (StopInfoSP()); - thread_sp->SetName (thread_name.empty() ? NULL : thread_name.c_str()); - - gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr); - if (exc_type != 0) - { - const size_t exc_data_size = exc_data.size(); - - thread_sp->SetStopInfo (StopInfoMachException::CreateStopReasonWithMachException (*thread_sp, - exc_type, - exc_data_size, - exc_data_size >= 1 ? exc_data[0] : 0, - exc_data_size >= 2 ? exc_data[1] : 0, - exc_data_size >= 3 ? exc_data[2] : 0)); - } - else - { - bool handled = false; - bool did_exec = false; - if (!reason.empty()) - { - if (reason.compare("trace") == 0) - { - thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); - handled = true; - } - else if (reason.compare("breakpoint") == 0) - { - addr_t pc = thread_sp->GetRegisterContext()->GetPC(); - lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); - if (bp_site_sp) - { - // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, - // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that - // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. - handled = true; - if (bp_site_sp->ValidForThisThread (thread_sp.get())) - { - thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID())); - } - else - { - StopInfoSP invalid_stop_info_sp; - thread_sp->SetStopInfo (invalid_stop_info_sp); - } - } - } - else if (reason.compare("trap") == 0) - { - // Let the trap just use the standard signal stop reason below... - } - else if (reason.compare("watchpoint") == 0) - { - StringExtractor desc_extractor(description.c_str()); - addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); - uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32); - watch_id_t watch_id = LLDB_INVALID_WATCH_ID; - if (wp_addr != LLDB_INVALID_ADDRESS) - { - WatchpointSP wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr); - if (wp_sp) - { - wp_sp->SetHardwareIndex(wp_index); - watch_id = wp_sp->GetID(); - } - } - if (watch_id == LLDB_INVALID_WATCH_ID) - { - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_WATCHPOINTS)); - if (log) log->Printf ("failed to find watchpoint"); - } - thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id)); - handled = true; - } - else if (reason.compare("exception") == 0) - { - thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException(*thread_sp, description.c_str())); - handled = true; - } - else if (reason.compare("exec") == 0) - { - did_exec = true; - thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithExec(*thread_sp)); - handled = true; - } - } - - if (!handled && signo && did_exec == false) - { - if (signo == SIGTRAP) - { - // Currently we are going to assume SIGTRAP means we are either - // hitting a breakpoint or hardware single stepping. - handled = true; - addr_t pc = thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset; - lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); - - if (bp_site_sp) - { - // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, - // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that - // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. - if (bp_site_sp->ValidForThisThread (thread_sp.get())) - { - if(m_breakpoint_pc_offset != 0) - thread_sp->GetRegisterContext()->SetPC(pc); - thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID())); - } - else - { - StopInfoSP invalid_stop_info_sp; - thread_sp->SetStopInfo (invalid_stop_info_sp); - } - } - else - { - // If we were stepping then assume the stop was the result of the trace. If we were - // not stepping then report the SIGTRAP. - // FIXME: We are still missing the case where we single step over a trap instruction. - if (thread_sp->GetTemporaryResumeState() == eStateStepping) - thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); - else - thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal(*thread_sp, signo, description.c_str())); - } - } - if (!handled) - thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo, description.c_str())); - } - - if (!description.empty()) - { - lldb::StopInfoSP stop_info_sp (thread_sp->GetStopInfo ()); - if (stop_info_sp) - { - const char *stop_info_desc = stop_info_sp->GetDescription(); - if (!stop_info_desc || !stop_info_desc[0]) - stop_info_sp->SetDescription (description.c_str()); - } - else - { - thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException (*thread_sp, description.c_str())); - } - } - } - } - } - return thread_sp; -} - -StateType -ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict) -{ - static ConstString g_key_tid("tid"); - static ConstString g_key_name("name"); - static ConstString g_key_reason("reason"); - static ConstString g_key_metype("metype"); - static ConstString g_key_medata("medata"); - static ConstString g_key_qaddr("qaddr"); - static ConstString g_key_registers("registers"); - static ConstString g_key_memory("memory"); - static ConstString g_key_address("address"); - static ConstString g_key_bytes("bytes"); - static ConstString g_key_description("description"); - - // Stop with signal and thread info - lldb::tid_t tid = LLDB_INVALID_THREAD_ID; - uint8_t signo = 0; - std::string value; - std::string thread_name; - std::string reason; - std::string description; - uint32_t exc_type = 0; - std::vector<addr_t> exc_data; - addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS; - StructuredData::Dictionary *registers_dict = nullptr; - - // Iterate through all of the thread dictionary key/value pairs from the structured data dictionary - - thread_dict->ForEach([this, &tid, ®isters_dict, &thread_name, &signo, &reason, &description, &exc_type, &exc_data, &thread_dispatch_qaddr](ConstString key, StructuredData::Object* object) -> bool - { - if (key == g_key_tid) - { - // thread in big endian hex - tid = object->GetIntegerValue(LLDB_INVALID_THREAD_ID); - } - else if (key == g_key_metype) - { - // exception type in big endian hex - exc_type = object->GetIntegerValue(0); - } - else if (key == g_key_medata) - { - // exception data in big endian hex - StructuredData::Array *array = object->GetAsArray(); - if (array) - { - array->ForEach([&exc_data](StructuredData::Object* object) -> bool { - exc_data.push_back(object->GetIntegerValue()); - return true; // Keep iterating through all array items - }); - } - } - else if (key == g_key_name) - { - thread_name = std::move(object->GetStringValue()); - } - else if (key == g_key_qaddr) - { - thread_dispatch_qaddr = object->GetIntegerValue(LLDB_INVALID_ADDRESS); - } - else if (key == g_key_reason) - { - reason = std::move(object->GetStringValue()); - } - else if (key == g_key_description) - { - description = std::move(object->GetStringValue()); - } - else if (key == g_key_registers) - { - registers_dict = object->GetAsDictionary(); - } - else if (key == g_key_memory) - { - StructuredData::Array *array = object->GetAsArray(); - if (array) - { - array->ForEach([this](StructuredData::Object* object) -> bool { - StructuredData::Dictionary *mem_cache_dict = object->GetAsDictionary(); - if (mem_cache_dict) - { - lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS; - if (mem_cache_dict->GetValueForKeyAsInteger<lldb::addr_t>("address", mem_cache_addr)) - { - if (mem_cache_addr != LLDB_INVALID_ADDRESS) - { - StringExtractor bytes; - if (mem_cache_dict->GetValueForKeyAsString("bytes", bytes.GetStringRef())) - { - bytes.SetFilePos(0); - - const size_t byte_size = bytes.GetStringRef().size()/2; - DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0)); - const size_t bytes_copied = bytes.GetHexBytes (data_buffer_sp->GetBytes(), byte_size, 0); - if (bytes_copied == byte_size) - m_memory_cache.AddL1CacheData(mem_cache_addr, data_buffer_sp); - } - } - } - } - return true; // Keep iterating through all array items - }); - } - - } - return true; // Keep iterating through all dictionary key/value pairs - }); - - - ThreadSP thread_sp = SetThreadStopInfo (tid, signo, thread_name, reason, description, exc_type, exc_data, thread_dispatch_qaddr); - if (thread_sp) - { - // Process any expedited register values so we don't have to read them with p/P or g/G packets - if (registers_dict) - { - ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get()); - - registers_dict->ForEach([gdb_thread](ConstString key, StructuredData::Object* object) -> bool { - const uint32_t reg = StringConvert::ToUInt32 (key.GetCString(), UINT32_MAX, 10); - if (reg != UINT32_MAX) - { - StringExtractor reg_value_extractor; - reg_value_extractor.GetStringRef() = std::move(object->GetStringValue()); - gdb_thread->PrivateSetRegisterValue (reg, reg_value_extractor); - } - return true; // Keep iterating through all array items - }); - } - return eStateStopped; - } - return eStateExited; -} StateType ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) @@ -2165,9 +1814,8 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) BuildDynamicRegisterInfo (true); } // Stop with signal and thread info - lldb::tid_t tid = LLDB_INVALID_THREAD_ID; const uint8_t signo = stop_packet.GetHexU8(); - std::string key; + std::string name; std::string value; std::string thread_name; std::string reason; @@ -2175,26 +1823,48 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) uint32_t exc_type = 0; std::vector<addr_t> exc_data; addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS; - typedef std::map<uint32_t, std::string> ExpeditedRegisterMap; - ExpeditedRegisterMap expedited_register_map; - while (stop_packet.GetNameColonValue(key, value)) + ThreadSP thread_sp; + ThreadGDBRemote *gdb_thread = NULL; + + while (stop_packet.GetNameColonValue(name, value)) { - if (key.compare("metype") == 0) + if (name.compare("metype") == 0) { // exception type in big endian hex exc_type = StringConvert::ToUInt32 (value.c_str(), 0, 16); } - else if (key.compare("medata") == 0) + else if (name.compare("medata") == 0) { // exception data in big endian hex exc_data.push_back(StringConvert::ToUInt64 (value.c_str(), 0, 16)); } - else if (key.compare("thread") == 0) + else if (name.compare("thread") == 0) { // thread in big endian hex - tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); + lldb::tid_t tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); + // m_thread_list_real does have its own mutex, but we need to + // hold onto the mutex between the call to m_thread_list_real.FindThreadByID(...) + // and the m_thread_list_real.AddThread(...) so it doesn't change on us + Mutex::Locker locker (m_thread_list_real.GetMutex ()); + thread_sp = m_thread_list_real.FindThreadByProtocolID(tid, false); + + if (!thread_sp) + { + // Create the thread if we need to + thread_sp.reset (new ThreadGDBRemote (*this, tid)); + Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_THREAD)); + if (log && log->GetMask().Test(GDBR_LOG_VERBOSE)) + log->Printf ("ProcessGDBRemote::%s Adding new thread: %p for thread ID: 0x%" PRIx64 ".\n", + __FUNCTION__, + static_cast<void*>(thread_sp.get()), + thread_sp->GetID()); + + m_thread_list_real.AddThread(thread_sp); + } + gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get()); + } - else if (key.compare("threads") == 0) + else if (name.compare("threads") == 0) { Mutex::Locker locker(m_thread_list_real.GetMutex()); m_thread_ids.clear(); @@ -2216,7 +1886,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) if (tid != LLDB_INVALID_THREAD_ID) m_thread_ids.push_back (tid); } - else if (key.compare("hexname") == 0) + else if (name.compare("hexname") == 0) { StringExtractor name_extractor; // Swap "value" over into "name_extractor" @@ -2225,19 +1895,19 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) name_extractor.GetHexByteString (value); thread_name.swap (value); } - else if (key.compare("name") == 0) + else if (name.compare("name") == 0) { thread_name.swap (value); } - else if (key.compare("qaddr") == 0) + else if (name.compare("qaddr") == 0) { thread_dispatch_qaddr = StringConvert::ToUInt64 (value.c_str(), 0, 16); } - else if (key.compare("reason") == 0) + else if (name.compare("reason") == 0) { reason.swap(value); } - else if (key.compare("description") == 0) + else if (name.compare("description") == 0) { StringExtractor desc_extractor; // Swap "value" over into "name_extractor" @@ -2246,49 +1916,34 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) desc_extractor.GetHexByteString (value); description.swap(value); } - else if (key.compare("memory") == 0) + else if (name.size() == 2 && ::isxdigit(name[0]) && ::isxdigit(name[1])) { - // Expedited memory. GDB servers can choose to send back expedited memory - // that can populate the L1 memory cache in the process so that things like - // the frame pointer backchain can be expedited. This will help stack - // backtracing be more efficient by not having to send as many memory read - // requests down the remote GDB server. - - // Key/value pair format: memory:<addr>=<bytes>; - // <addr> is a number whose base will be interpreted by the prefix: - // "0x[0-9a-fA-F]+" for hex - // "0[0-7]+" for octal - // "[1-9]+" for decimal - // <bytes> is native endian ASCII hex bytes just like the register values - llvm::StringRef value_ref(value); - std::pair<llvm::StringRef, llvm::StringRef> pair; - pair = value_ref.split('='); - if (!pair.first.empty() && !pair.second.empty()) + // We have a register number that contains an expedited + // register value. Lets supply this register to our thread + // so it won't have to go and read it. + if (gdb_thread) { - std::string addr_str(pair.first.str()); - const lldb::addr_t mem_cache_addr = StringConvert::ToUInt64(addr_str.c_str(), LLDB_INVALID_ADDRESS, 0); - if (mem_cache_addr != LLDB_INVALID_ADDRESS) + uint32_t reg = StringConvert::ToUInt32 (name.c_str(), UINT32_MAX, 16); + + if (reg != UINT32_MAX) { - StringExtractor bytes; - bytes.GetStringRef() = std::move(pair.second.str()); - const size_t byte_size = bytes.GetStringRef().size()/2; - DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0)); - const size_t bytes_copied = bytes.GetHexBytes (data_buffer_sp->GetBytes(), byte_size, 0); - if (bytes_copied == byte_size) - m_memory_cache.AddL1CacheData(mem_cache_addr, data_buffer_sp); + StringExtractor reg_value_extractor; + // Swap "value" over into "reg_value_extractor" + reg_value_extractor.GetStringRef().swap(value); + if (!gdb_thread->PrivateSetRegisterValue (reg, reg_value_extractor)) + { + Host::SetCrashDescriptionWithFormat("Setting thread register '%s' (decoded to %u (0x%x)) with value '%s' for stop packet: '%s'", + name.c_str(), + reg, + reg, + reg_value_extractor.GetStringRef().c_str(), + stop_packet.GetStringRef().c_str()); + } } } } - else if (key.size() == 2 && ::isxdigit(key[0]) && ::isxdigit(key[1])) - { - uint32_t reg = StringConvert::ToUInt32 (key.c_str(), UINT32_MAX, 16); - if (reg != UINT32_MAX) - expedited_register_map[reg] = std::move(value); - } } - ThreadSP thread_sp = SetThreadStopInfo (tid, signo, thread_name, reason, description, exc_type, exc_data, thread_dispatch_qaddr); - // If the response is old style 'S' packet which does not provide us with thread information // then update the thread list and choose the first one. if (!thread_sp) @@ -2299,23 +1954,156 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) { Mutex::Locker locker (m_thread_list_real.GetMutex ()); thread_sp = m_thread_list_real.FindThreadByProtocolID (m_thread_ids.front (), false); + if (thread_sp) + gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get ()); } } - if (thread_sp && !expedited_register_map.empty()) + if (thread_sp) { - // Process any expedited register values so we don't have to read them with p/P or g/G packets - ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get()); - for (const auto &pair : expedited_register_map) + // Clear the stop info just in case we don't set it to anything + thread_sp->SetStopInfo (StopInfoSP()); + + gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr); + gdb_thread->SetName (thread_name.empty() ? NULL : thread_name.c_str()); + if (exc_type != 0) + { + const size_t exc_data_size = exc_data.size(); + + thread_sp->SetStopInfo (StopInfoMachException::CreateStopReasonWithMachException (*thread_sp, + exc_type, + exc_data_size, + exc_data_size >= 1 ? exc_data[0] : 0, + exc_data_size >= 2 ? exc_data[1] : 0, + exc_data_size >= 3 ? exc_data[2] : 0)); + } + else { - StringExtractor reg_value_extractor; - reg_value_extractor.GetStringRef() = pair.second; - if (!gdb_thread->PrivateSetRegisterValue (pair.first, reg_value_extractor)) + bool handled = false; + bool did_exec = false; + if (!reason.empty()) { - Host::SetCrashDescriptionWithFormat("Setting thread register '0x%2.2x' with value '%s' for stop packet: '%s'", - pair.first, - reg_value_extractor.GetStringRef().c_str(), - stop_packet.GetStringRef().c_str()); + if (reason.compare("trace") == 0) + { + thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); + handled = true; + } + else if (reason.compare("breakpoint") == 0) + { + addr_t pc = thread_sp->GetRegisterContext()->GetPC(); + lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); + if (bp_site_sp) + { + // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, + // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that + // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. + handled = true; + if (bp_site_sp->ValidForThisThread (thread_sp.get())) + { + thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID())); + } + else + { + StopInfoSP invalid_stop_info_sp; + thread_sp->SetStopInfo (invalid_stop_info_sp); + } + } + } + else if (reason.compare("trap") == 0) + { + // Let the trap just use the standard signal stop reason below... + } + else if (reason.compare("watchpoint") == 0) + { + StringExtractor desc_extractor(description.c_str()); + addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); + uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32); + watch_id_t watch_id = LLDB_INVALID_WATCH_ID; + if (wp_addr != LLDB_INVALID_ADDRESS) + { + WatchpointSP wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr); + if (wp_sp) + { + wp_sp->SetHardwareIndex(wp_index); + watch_id = wp_sp->GetID(); + } + } + if (watch_id == LLDB_INVALID_WATCH_ID) + { + Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_WATCHPOINTS)); + if (log) log->Printf ("failed to find watchpoint"); + } + thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id)); + handled = true; + } + else if (reason.compare("exception") == 0) + { + thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException(*thread_sp, description.c_str())); + handled = true; + } + else if (reason.compare("exec") == 0) + { + did_exec = true; + thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithExec(*thread_sp)); + handled = true; + } + } + + if (!handled && signo && did_exec == false) + { + if (signo == SIGTRAP) + { + // Currently we are going to assume SIGTRAP means we are either + // hitting a breakpoint or hardware single stepping. + handled = true; + addr_t pc = thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset; + lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); + + if (bp_site_sp) + { + // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, + // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that + // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. + if (bp_site_sp->ValidForThisThread (thread_sp.get())) + { + if(m_breakpoint_pc_offset != 0) + thread_sp->GetRegisterContext()->SetPC(pc); + thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID())); + } + else + { + StopInfoSP invalid_stop_info_sp; + thread_sp->SetStopInfo (invalid_stop_info_sp); + } + } + else + { + // If we were stepping then assume the stop was the result of the trace. If we were + // not stepping then report the SIGTRAP. + // FIXME: We are still missing the case where we single step over a trap instruction. + if (thread_sp->GetTemporaryResumeState() == eStateStepping) + thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); + else + thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal(*thread_sp, signo, description.c_str())); + } + } + if (!handled) + thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo, description.c_str())); + } + + if (!description.empty()) + { + lldb::StopInfoSP stop_info_sp (thread_sp->GetStopInfo ()); + if (stop_info_sp) + { + const char *stop_info_desc = stop_info_sp->GetDescription(); + if (!stop_info_desc || !stop_info_desc[0]) + stop_info_sp->SetDescription (description.c_str()); + } + else + { + thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException (*thread_sp, description.c_str())); + } } } } @@ -2375,11 +2163,6 @@ ProcessGDBRemote::RefreshStateAfterStop () m_initial_tid = LLDB_INVALID_THREAD_ID; } - // Fetch the threads via an efficient packet that gets stop infos for all threads - // only if we have more than one thread - if (m_thread_ids.size() > 1) - m_threads_info_sp = m_gdb_comm.GetThreadsInfo(); - // Let all threads recover from stopping and do any clean up based // on the previous thread state (if any). m_thread_list_real.RefreshStateAfterStop(); diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 29ca17ef9cb..02f449ffca4 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -323,9 +323,6 @@ protected: void GetMaxMemorySize(); - bool - CalculateThreadStopInfo (ThreadGDBRemote *thread); - //------------------------------------------------------------------ /// Broadcaster event bits definitions. //------------------------------------------------------------------ @@ -349,7 +346,6 @@ protected: typedef std::vector< std::pair<lldb::tid_t,int> > tid_sig_collection; typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap; tid_collection m_thread_ids; // Thread IDs for all threads. This list gets updated after stopping - StructuredData::ObjectSP m_threads_info_sp; // Stop info for all threads if "jThreadsInfo" packet is supported tid_collection m_continue_c_tids; // 'c' for continue tid_sig_collection m_continue_C_tids; // 'C' for continue with signal tid_collection m_continue_s_tids; // 's' for step @@ -383,19 +379,6 @@ protected: lldb::StateType SetThreadStopInfo (StringExtractor& stop_packet); - lldb::StateType - SetThreadStopInfo (StructuredData::Dictionary *thread_dict); - - lldb::ThreadSP - SetThreadStopInfo (lldb::tid_t tid, - uint8_t signo, - const std::string &thread_name, - const std::string &reason, - const std::string &description, - uint32_t exc_type, - const std::vector<lldb::addr_t> &exc_data, - lldb::addr_t thread_dispatch_qaddr); - void HandleStopReplySequence (); diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index 74b51fd917c..e4108edc03f 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -284,7 +284,12 @@ ThreadGDBRemote::CalculateStopInfo () { ProcessSP process_sp (GetProcess()); if (process_sp) - return static_cast<ProcessGDBRemote *>(process_sp.get())->CalculateThreadStopInfo(this); + { + StringExtractorGDBRemote stop_packet; + ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get()); + if (gdb_process->GetGDBRemote().GetThreadStopInfo(GetProtocolID(), stop_packet)) + return gdb_process->SetThreadStopInfo (stop_packet) == eStateStopped; + } return false; } diff --git a/lldb/source/Target/Memory.cpp b/lldb/source/Target/Memory.cpp index e61b3ab91e7..934bc967b68 100644 --- a/lldb/source/Target/Memory.cpp +++ b/lldb/source/Target/Memory.cpp @@ -14,9 +14,8 @@ // Other libraries and framework includes // Project includes #include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/RangeMap.h" #include "lldb/Core/State.h" +#include "lldb/Core/Log.h" #include "lldb/Target/Process.h" using namespace lldb; @@ -26,12 +25,11 @@ using namespace lldb_private; // MemoryCache constructor //---------------------------------------------------------------------- MemoryCache::MemoryCache(Process &process) : - m_mutex (Mutex::eMutexTypeRecursive), - m_L1_cache (), - m_L2_cache (), - m_invalid_ranges (), m_process (process), - m_L2_cache_line_byte_size (process.GetMemoryCacheLineSize()) + m_cache_line_byte_size (process.GetMemoryCacheLineSize()), + m_mutex (Mutex::eMutexTypeRecursive), + m_cache (), + m_invalid_ranges () { } @@ -46,24 +44,10 @@ void MemoryCache::Clear(bool clear_invalid_ranges) { Mutex::Locker locker (m_mutex); - m_L1_cache.clear(); - m_L2_cache.clear(); + m_cache.clear(); if (clear_invalid_ranges) m_invalid_ranges.Clear(); - m_L2_cache_line_byte_size = m_process.GetMemoryCacheLineSize(); -} - -void -MemoryCache::AddL1CacheData(lldb::addr_t addr, const void *src, size_t src_len) -{ - AddL1CacheData(addr,DataBufferSP (new DataBufferHeap(DataBufferHeap(src, src_len)))); -} - -void -MemoryCache::AddL1CacheData(lldb::addr_t addr, const DataBufferSP &data_buffer_sp) -{ - Mutex::Locker locker (m_mutex); - m_L1_cache[addr] = data_buffer_sp; + m_cache_line_byte_size = m_process.GetMemoryCacheLineSize(); } void @@ -73,44 +57,29 @@ MemoryCache::Flush (addr_t addr, size_t size) return; Mutex::Locker locker (m_mutex); + if (m_cache.empty()) + return; - // Erase any blocks from the L1 cache that intersect with the flush range - if (!m_L1_cache.empty()) + const uint32_t cache_line_byte_size = m_cache_line_byte_size; + const addr_t end_addr = (addr + size - 1); + const addr_t first_cache_line_addr = addr - (addr % cache_line_byte_size); + const addr_t last_cache_line_addr = end_addr - (end_addr % cache_line_byte_size); + // Watch for overflow where size will cause us to go off the end of the + // 64 bit address space + uint32_t num_cache_lines; + if (last_cache_line_addr >= first_cache_line_addr) + num_cache_lines = ((last_cache_line_addr - first_cache_line_addr)/cache_line_byte_size) + 1; + else + num_cache_lines = (UINT64_MAX - first_cache_line_addr + 1)/cache_line_byte_size; + + uint32_t cache_idx = 0; + for (addr_t curr_addr = first_cache_line_addr; + cache_idx < num_cache_lines; + curr_addr += cache_line_byte_size, ++cache_idx) { - AddrRange flush_range(addr, size); - BlockMap::iterator pos = m_L1_cache.lower_bound(addr); - while (pos != m_L1_cache.end()) - { - AddrRange chunk_range(pos->first, pos->second->GetByteSize()); - if (!chunk_range.DoesIntersect(flush_range)) - break; - pos = m_L1_cache.erase(pos); - } - } - - if (!m_L2_cache.empty()) - { - const uint32_t cache_line_byte_size = m_L2_cache_line_byte_size; - const addr_t end_addr = (addr + size - 1); - const addr_t first_cache_line_addr = addr - (addr % cache_line_byte_size); - const addr_t last_cache_line_addr = end_addr - (end_addr % cache_line_byte_size); - // Watch for overflow where size will cause us to go off the end of the - // 64 bit address space - uint32_t num_cache_lines; - if (last_cache_line_addr >= first_cache_line_addr) - num_cache_lines = ((last_cache_line_addr - first_cache_line_addr)/cache_line_byte_size) + 1; - else - num_cache_lines = (UINT64_MAX - first_cache_line_addr + 1)/cache_line_byte_size; - - uint32_t cache_idx = 0; - for (addr_t curr_addr = first_cache_line_addr; - cache_idx < num_cache_lines; - curr_addr += cache_line_byte_size, ++cache_idx) - { - BlockMap::iterator pos = m_L2_cache.find (curr_addr); - if (pos != m_L2_cache.end()) - m_L2_cache.erase(pos); - } + BlockMap::iterator pos = m_cache.find (curr_addr); + if (pos != m_cache.end()) + m_cache.erase(pos); } } @@ -153,39 +122,6 @@ MemoryCache::Read (addr_t addr, { size_t bytes_left = dst_len; - // Check the L1 cache for a range that contain the entire memory read. - // If we find a range in the L1 cache that does, we use it. Else we fall - // back to reading memory in m_L2_cache_line_byte_size byte sized chunks. - // The L1 cache contains chunks of memory that are not required to be - // m_L2_cache_line_byte_size bytes in size, so we don't try anything - // tricky when reading from them (no partial reads from the L1 cache). - - Mutex::Locker locker(m_mutex); - if (!m_L1_cache.empty()) - { - AddrRange read_range(addr, dst_len); - BlockMap::iterator pos = m_L1_cache.lower_bound(addr); - if (pos != m_L1_cache.end()) - { - AddrRange chunk_range(pos->first, pos->second->GetByteSize()); - bool match = chunk_range.Contains(read_range); - if (!match && pos != m_L1_cache.begin()) - { - --pos; - chunk_range.SetRangeBase(pos->first); - chunk_range.SetByteSize(pos->second->GetByteSize()); - match = chunk_range.Contains(read_range); - } - - if (match) - { - memcpy(dst, pos->second->GetBytes() + addr - chunk_range.GetRangeBase(), dst_len); - return dst_len; - } - } - } - - // If this memory read request is larger than the cache line size, then // we (1) try to read as much of it at once as possible, and (2) don't // add the data to the memory cache. We don't want to split a big read @@ -193,22 +129,19 @@ MemoryCache::Read (addr_t addr, // request, it is unlikely that the caller function will ask for the next // 4 bytes after the large memory read - so there's little benefit to saving // it in the cache. - if (dst && dst_len > m_L2_cache_line_byte_size) + if (dst && dst_len > m_cache_line_byte_size) { - size_t bytes_read = m_process.ReadMemoryFromInferior (addr, dst, dst_len, error); - // Add this non block sized range to the L1 cache if we actually read anything - if (bytes_read > 0) - AddL1CacheData(addr, dst, bytes_read); - return bytes_read; + return m_process.ReadMemoryFromInferior (addr, dst, dst_len, error); } if (dst && bytes_left > 0) { - const uint32_t cache_line_byte_size = m_L2_cache_line_byte_size; + const uint32_t cache_line_byte_size = m_cache_line_byte_size; uint8_t *dst_buf = (uint8_t *)dst; addr_t curr_addr = addr - (addr % cache_line_byte_size); addr_t cache_offset = addr - curr_addr; - + Mutex::Locker locker (m_mutex); + while (bytes_left > 0) { if (m_invalid_ranges.FindEntryThatContains(curr_addr)) @@ -217,8 +150,8 @@ MemoryCache::Read (addr_t addr, return dst_len - bytes_left; } - BlockMap::const_iterator pos = m_L2_cache.find (curr_addr); - BlockMap::const_iterator end = m_L2_cache.end (); + BlockMap::const_iterator pos = m_cache.find (curr_addr); + BlockMap::const_iterator end = m_cache.end (); if (pos != end) { @@ -275,7 +208,7 @@ MemoryCache::Read (addr_t addr, if (process_bytes_read != cache_line_byte_size) data_buffer_heap_ap->SetByteSize (process_bytes_read); - m_L2_cache[curr_addr] = DataBufferSP (data_buffer_heap_ap.release()); + m_cache[curr_addr] = DataBufferSP (data_buffer_heap_ap.release()); // We have read data and put it into the cache, continue through the // loop again to get the data out of the cache... } diff --git a/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj b/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj index c82421238af..f7cbc1338fb 100644 --- a/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj +++ b/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj @@ -55,7 +55,6 @@ 26203D1D1641EFB200A662F7 /* com.apple.debugserver.internal.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.debugserver.internal.plist; sourceTree = "<group>"; }; 26242C390DDBD33C0054A4CC /* debugserver-entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "debugserver-entitlements.plist"; sourceTree = "<group>"; }; 264D5D571293835600ED4C01 /* DNBArch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DNBArch.cpp; sourceTree = "<group>"; }; - 264F679A1B2F9EB200140093 /* JSONGenerator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSONGenerator.h; sourceTree = "<group>"; }; 26593A060D4931CC001C9FE3 /* ChangeLog */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ChangeLog; sourceTree = "<group>"; }; 2660D9CC1192280900958FBD /* StringExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringExtractor.cpp; path = ../../source/Utility/StringExtractor.cpp; sourceTree = SOURCE_ROOT; }; 2660D9CD1192280900958FBD /* StringExtractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringExtractor.h; path = ../../source/Utility/StringExtractor.h; sourceTree = SOURCE_ROOT; }; @@ -233,7 +232,6 @@ 26C637E20C71334A0024798E /* DNBRegisterInfo.cpp */, 260E7332114BFFE600D1DFB3 /* DNBThreadResumeActions.h */, 260E7331114BFFE600D1DFB3 /* DNBThreadResumeActions.cpp */, - 264F679A1B2F9EB200140093 /* JSONGenerator.h */, AF67AC000D34604D0022D128 /* PseudoTerminal.h */, AF67ABFF0D34604D0022D128 /* PseudoTerminal.cpp */, 26C637FD0C71334A0024798E /* PThreadCondition.h */, diff --git a/lldb/tools/debugserver/source/JSONGenerator.h b/lldb/tools/debugserver/source/JSONGenerator.h deleted file mode 100644 index 423b2bd5792..00000000000 --- a/lldb/tools/debugserver/source/JSONGenerator.h +++ /dev/null @@ -1,490 +0,0 @@ -//===-- JSONGenerator.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef __JSONGenerator_h_ -#define __JSONGenerator_h_ - -// C Includes -// C++ Includes - -#include <iomanip> -#include <sstream> -#include <string> -#include <utility> -#include <vector> - -//---------------------------------------------------------------------- -/// @class JSONGenerator JSONGenerator.h -/// @brief A class which can construct structured data for the sole purpose -/// of printing it in JSON format. -/// -/// A stripped down version of lldb's StructuredData objects which are much -/// general purpose. This variant is intended only for assembling information -/// and printing it as a JSON string. -//---------------------------------------------------------------------- - -class JSONGenerator -{ -public: - - class Object; - class Array; - class Integer; - class Float; - class Boolean; - class String; - class Dictionary; - class Generic; - - typedef std::shared_ptr<Object> ObjectSP; - typedef std::shared_ptr<Array> ArraySP; - typedef std::shared_ptr<Integer> IntegerSP; - typedef std::shared_ptr<Float> FloatSP; - typedef std::shared_ptr<Boolean> BooleanSP; - typedef std::shared_ptr<String> StringSP; - typedef std::shared_ptr<Dictionary> DictionarySP; - typedef std::shared_ptr<Generic> GenericSP; - - enum class Type - { - eTypeInvalid = -1, - eTypeNull = 0, - eTypeGeneric, - eTypeArray, - eTypeInteger, - eTypeFloat, - eTypeBoolean, - eTypeString, - eTypeDictionary - }; - - class Object : - public std::enable_shared_from_this<Object> - { - public: - - Object (Type t = Type::eTypeInvalid) : - m_type (t) - { - } - - virtual ~Object () - { - } - - virtual bool - IsValid() const - { - return true; - } - - virtual void - Clear () - { - m_type = Type::eTypeInvalid; - } - - Type - GetType () const - { - return m_type; - } - - void - SetType (Type t) - { - m_type = t; - } - - Array * - GetAsArray () - { - if (m_type == Type::eTypeArray) - return (Array *)this; - return NULL; - } - - Dictionary * - GetAsDictionary () - { - if (m_type == Type::eTypeDictionary) - return (Dictionary *)this; - return NULL; - } - - Integer * - GetAsInteger () - { - if (m_type == Type::eTypeInteger) - return (Integer *)this; - return NULL; - } - - Float * - GetAsFloat () - { - if (m_type == Type::eTypeFloat) - return (Float *)this; - return NULL; - } - - Boolean * - GetAsBoolean () - { - if (m_type == Type::eTypeBoolean) - return (Boolean *)this; - return NULL; - } - - String * - GetAsString () - { - if (m_type == Type::eTypeString) - return (String *)this; - return NULL; - } - - Generic * - GetAsGeneric() - { - if (m_type == Type::eTypeGeneric) - return (Generic *)this; - return NULL; - } - - virtual void - Dump (std::ostream &s) const = 0; - - private: - Type m_type; - }; - - class Array : public Object - { - public: - Array () : - Object (Type::eTypeArray) - { - } - - virtual - ~Array() - { - } - - void - AddItem(ObjectSP item) - { - m_items.push_back(item); - } - - void Dump(std::ostream &s) const override - { - s << "["; - const size_t arrsize = m_items.size(); - for (size_t i = 0; i < arrsize; ++i) - { - m_items[i]->Dump(s); - if (i + 1 < arrsize) - s << ","; - } - s << "]"; - } - - protected: - typedef std::vector<ObjectSP> collection; - collection m_items; - }; - - - class Integer : public Object - { - public: - Integer (uint64_t value = 0) : - Object (Type::eTypeInteger), - m_value (value) - { - } - - virtual ~Integer() - { - } - - void - SetValue (uint64_t value) - { - m_value = value; - } - - void Dump(std::ostream &s) const override - { - s << m_value; - } - - protected: - uint64_t m_value; - }; - - class Float : public Object - { - public: - Float (double d = 0.0) : - Object (Type::eTypeFloat), - m_value (d) - { - } - - virtual ~Float() - { - } - - void - SetValue (double value) - { - m_value = value; - } - - void Dump(std::ostream &s) const override - { - s << m_value; - } - - protected: - double m_value; - }; - - class Boolean : public Object - { - public: - Boolean (bool b = false) : - Object (Type::eTypeBoolean), - m_value (b) - { - } - - virtual ~Boolean() - { - } - - void - SetValue (bool value) - { - m_value = value; - } - - void Dump(std::ostream &s) const override - { - if (m_value == true) - s << "true"; - else - s << "false"; - } - - protected: - bool m_value; - }; - - - - class String : public Object - { - public: - String () : - Object (Type::eTypeString), - m_value () - { - } - - String (const std::string &s) : - Object (Type::eTypeString), - m_value (s) - { - } - - String (const std::string &&s) : - Object (Type::eTypeString), - m_value (s) - { - } - - void - SetValue (const std::string &string) - { - m_value = string; - } - - void Dump(std::ostream &s) const override - { - std::string quoted; - const size_t strsize = m_value.size(); - for (size_t i = 0; i < strsize ; ++i) - { - char ch = m_value[i]; - if (ch == '"') - quoted.push_back ('\\'); - quoted.push_back (ch); - } - s << '"' << quoted.c_str() << '"'; - } - - protected: - std::string m_value; - }; - - class Dictionary : public Object - { - public: - Dictionary () : - Object (Type::eTypeDictionary), - m_dict () - { - } - - virtual ~Dictionary() - { - } - - void - AddItem (std::string key, ObjectSP value) - { - m_dict.push_back(Pair(key, value)); - } - - void - AddIntegerItem (std::string key, uint64_t value) - { - AddItem (key, ObjectSP (new Integer(value))); - } - - void - AddFloatItem (std::string key, double value) - { - AddItem (key, ObjectSP (new Float(value))); - } - - void - AddStringItem (std::string key, std::string value) - { - AddItem (key, ObjectSP (new String(std::move(value)))); - } - - void - AddBytesAsHexASCIIString (std::string key, const uint8_t *src, size_t src_len) - { - if (src && src_len) - { - std::ostringstream strm; - for (size_t i = 0; i < src_len; i++) - strm << std::setfill('0') << std::hex << std::right << std::setw(2) << ((uint32_t)(src[i])); - AddItem (key, ObjectSP (new String(std::move(strm.str())))); - } - else - { - AddItem (key, ObjectSP (new String())); - } - } - - void - AddBooleanItem (std::string key, bool value) - { - AddItem (key, ObjectSP (new Boolean(value))); - } - - void Dump(std::ostream &s) const override - { - bool have_printed_one_elem = false; - s << "{"; - for (collection::const_iterator iter = m_dict.begin(); iter != m_dict.end(); ++iter) - { - if (have_printed_one_elem == false) - { - have_printed_one_elem = true; - } - else - { - s << ","; - } - s << "\"" << iter->first.c_str() << "\":"; - iter->second->Dump(s); - } - s << "}"; - } - - protected: - // Keep the dictionary as a vector so the dictionary doesn't reorder itself when you dump it - // We aren't accessing keys by name, so this won't affect performance - typedef std::pair<std::string, ObjectSP> Pair; - typedef std::vector<Pair> collection; - collection m_dict; - }; - - class Null : public Object - { - public: - Null () : - Object (Type::eTypeNull) - { - } - - virtual ~Null() - { - } - - bool - IsValid() const override - { - return false; - } - - void Dump(std::ostream &s) const override - { - s << "null"; - } - - protected: - }; - - class Generic : public Object - { - public: - explicit Generic(void *object = nullptr) - : Object(Type::eTypeGeneric) - , m_object(object) - { - } - - void - SetValue(void *value) - { - m_object = value; - } - - void * - GetValue() const - { - return m_object; - } - - bool - IsValid() const override - { - return m_object != nullptr; - } - - void Dump(std::ostream &s) const override; - - private: - void *m_object; - }; - -}; // class JSONGenerator - - - -#endif // __JSONGenerator_h_ diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp index 00a0c9bd4bb..2385246a200 100644 --- a/lldb/tools/debugserver/source/RNBRemote.cpp +++ b/lldb/tools/debugserver/source/RNBRemote.cpp @@ -29,7 +29,6 @@ #include "DNBDataRef.h" #include "DNBLog.h" #include "DNBThreadResumeActions.h" -#include "JSONGenerator.h" #include "RNBContext.h" #include "RNBServices.h" #include "RNBSocket.h" @@ -196,7 +195,6 @@ RNBRemote::CreatePacketTable () t.push_back (Packet (query_process_info, &RNBRemote::HandlePacket_qProcessInfo, NULL, "qProcessInfo", "Replies with multiple 'key:value;' tuples appended to each other.")); // t.push_back (Packet (query_symbol_lookup, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "qSymbol", "Notify that host debugger is ready to do symbol lookups")); t.push_back (Packet (json_query_thread_extended_info, &RNBRemote::HandlePacket_jThreadExtendedInfo, NULL, "jThreadExtendedInfo", "Replies with JSON data of thread extended information.")); - t.push_back (Packet (json_query_threads_info, &RNBRemote::HandlePacket_jThreadsInfo , NULL, "jThreadsInfo", "Replies with JSON data with information about all threads.")); t.push_back (Packet (start_noack_mode, &RNBRemote::HandlePacket_QStartNoAckMode , NULL, "QStartNoAckMode", "Request that " DEBUGSERVER_PROGRAM_NAME " stop acking remote protocol packets")); t.push_back (Packet (prefix_reg_packets_with_tid, &RNBRemote::HandlePacket_QThreadSuffixSupported , NULL, "QThreadSuffixSupported", "Check if thread specific packets (register packets 'g', 'G', 'p', and 'P') support having the thread ID appended to the end of the command")); t.push_back (Packet (set_logging_mode, &RNBRemote::HandlePacket_QSetLogging , NULL, "QSetLogging:", "Check if register packets ('g', 'G', 'p', and 'P' support having the thread ID prefix")); @@ -2454,52 +2452,6 @@ gdb_regnum_with_fixed_width_hex_register_value (std::ostream& ostrm, } } -struct StackMemory -{ - uint8_t bytes[2*sizeof(nub_addr_t)]; - nub_size_t length; -}; -typedef std::map<nub_addr_t, StackMemory> StackMemoryMap; - - -static void -ReadStackMemory (nub_process_t pid, nub_thread_t tid, StackMemoryMap &stack_mmap) -{ - DNBRegisterValue reg_value; - if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC, GENERIC_REGNUM_FP, ®_value)) - { - uint32_t frame_count = 0; - uint64_t fp = 0; - if (reg_value.info.size == 4) - fp = reg_value.value.uint32; - else - fp = reg_value.value.uint64; - while (fp != 0) - { - // Make sure we never recurse more than 256 times so we don't recurse too far or - // store up too much memory in the expedited cache - if (++frame_count > 256) - break; - - const nub_size_t read_size = reg_value.info.size*2; - StackMemory stack_memory; - stack_memory.length = read_size; - if (DNBProcessMemoryRead(pid, fp, read_size, stack_memory.bytes) != read_size) - break; - // Make sure we don't try to put the same stack memory in more than once - if (stack_mmap.find(fp) != stack_mmap.end()) - break; - // Put the entry into the cache - stack_mmap[fp] = stack_memory; - // Dereference the frame pointer to get to the previous frame pointer - if (reg_value.info.size == 4) - fp = ((uint32_t *)stack_memory.bytes)[0]; - else - fp = ((uint64_t *)stack_memory.bytes)[0]; - } - } -} - rnb_err_t RNBRemote::SendStopReplyPacketForThread (nub_thread_t tid) { @@ -2626,26 +2578,11 @@ RNBRemote::SendStopReplyPacketForThread (nub_thread_t tid) } else if (tid_stop_info.details.exception.type) { - ostrm << "metype:" << std::hex << tid_stop_info.details.exception.type << ';'; - ostrm << "mecount:" << std::hex << tid_stop_info.details.exception.data_count << ';'; + ostrm << "metype:" << std::hex << tid_stop_info.details.exception.type << ";"; + ostrm << "mecount:" << std::hex << tid_stop_info.details.exception.data_count << ";"; for (int i = 0; i < tid_stop_info.details.exception.data_count; ++i) - ostrm << "medata:" << std::hex << tid_stop_info.details.exception.data[i] << ';'; + ostrm << "medata:" << std::hex << tid_stop_info.details.exception.data[i] << ";"; } - - // Add expedited stack memory so stack backtracing doesn't need to read anything from the - // frame pointer chain. - StackMemoryMap stack_mmap; - ReadStackMemory (pid, tid, stack_mmap); - if (!stack_mmap.empty()) - { - for (const auto &stack_memory : stack_mmap) - { - ostrm << "memory:" << HEXBASE << stack_memory.first << '='; - append_hex_value (ostrm, stack_memory.second.bytes, stack_memory.second.length, false); - ostrm << ';'; - } - } - return SendPacket (ostrm.str ()); } return SendPacket("E51"); @@ -4825,136 +4762,11 @@ get_integer_value_for_key_name_from_json (const char *key, const char *json_stri } rnb_err_t -RNBRemote::HandlePacket_jThreadsInfo (const char *p) -{ - JSONGenerator::Array threads_array; - - std::ostringstream json; - std::ostringstream reply_strm; - // If we haven't run the process yet, return an error. - if (m_ctx.HasValidProcessID()) - { - nub_process_t pid = m_ctx.ProcessID(); - - nub_size_t numthreads = DNBProcessGetNumThreads (pid); - for (nub_size_t i = 0; i < numthreads; ++i) - { - nub_thread_t tid = DNBProcessGetThreadAtIndex (pid, i); - - struct DNBThreadStopInfo tid_stop_info; - - JSONGenerator::DictionarySP thread_dict_sp(new JSONGenerator::Dictionary()); - - thread_dict_sp->AddIntegerItem("tid", tid); - - std::string reason_value("none"); - if (DNBThreadGetStopReason (pid, tid, &tid_stop_info)) - { - switch (tid_stop_info.reason) - { - case eStopTypeInvalid: - break; - case eStopTypeSignal: - if (tid_stop_info.details.signal.signo != 0) - reason_value = "signal"; - break; - case eStopTypeException: - if (tid_stop_info.details.exception.type != 0) - reason_value = "exception"; - break; - case eStopTypeExec: - reason_value = "exec"; - break; - } - if (tid_stop_info.reason == eStopTypeSignal) - { - thread_dict_sp->AddIntegerItem("signal", tid_stop_info.details.signal.signo); - } - else if (tid_stop_info.reason == eStopTypeException && tid_stop_info.details.exception.type != 0) - { - thread_dict_sp->AddIntegerItem("metype", tid_stop_info.details.exception.type); - JSONGenerator::ArraySP medata_array_sp(new JSONGenerator::Array()); - for (nub_size_t i=0; i<tid_stop_info.details.exception.data_count; ++i) - { - medata_array_sp->AddItem(JSONGenerator::IntegerSP(new JSONGenerator::Integer(tid_stop_info.details.exception.data[i]))); - } - thread_dict_sp->AddItem("medata", medata_array_sp); - } - } - - thread_dict_sp->AddStringItem("reason", reason_value); - - const char *thread_name = DNBThreadGetName (pid, tid); - if (thread_name && thread_name[0]) - thread_dict_sp->AddStringItem("name", thread_name); - - - thread_identifier_info_data_t thread_ident_info; - if (DNBThreadGetIdentifierInfo (pid, tid, &thread_ident_info)) - { - if (thread_ident_info.dispatch_qaddr != 0) - thread_dict_sp->AddIntegerItem("qaddr", thread_ident_info.dispatch_qaddr); - } - DNBRegisterValue reg_value; - - if (g_reg_entries != NULL) - { - JSONGenerator::DictionarySP registers_dict_sp(new JSONGenerator::Dictionary()); - - for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) - { - // Expedite all registers in the first register set that aren't - // contained in other registers - if (g_reg_entries[reg].nub_info.set == 1 && - g_reg_entries[reg].nub_info.value_regs == NULL) - { - if (!DNBThreadGetRegisterValueByID (pid, tid, g_reg_entries[reg].nub_info.set, g_reg_entries[reg].nub_info.reg, ®_value)) - continue; - - std::ostringstream reg_num; - reg_num << std::dec << g_reg_entries[reg].gdb_regnum; - // Encode native byte ordered bytes as hex ascii - registers_dict_sp->AddBytesAsHexASCIIString(reg_num.str(), reg_value.value.v_uint8, g_reg_entries[reg].nub_info.size); - } - } - thread_dict_sp->AddItem("registers", registers_dict_sp); - } - - // Add expedited stack memory so stack backtracing doesn't need to read anything from the - // frame pointer chain. - StackMemoryMap stack_mmap; - ReadStackMemory (pid, tid, stack_mmap); - if (!stack_mmap.empty()) - { - JSONGenerator::ArraySP memory_array_sp(new JSONGenerator::Array()); - - for (const auto &stack_memory : stack_mmap) - { - JSONGenerator::DictionarySP stack_memory_sp(new JSONGenerator::Dictionary()); - stack_memory_sp->AddIntegerItem("address", stack_memory.first); - stack_memory_sp->AddBytesAsHexASCIIString("bytes", stack_memory.second.bytes, stack_memory.second.length); - memory_array_sp->AddItem(stack_memory_sp); - } - thread_dict_sp->AddItem("memory", memory_array_sp); - } - threads_array.AddItem(thread_dict_sp); - } - - std::ostringstream strm; - threads_array.Dump (strm); - std::string binary_packet = binary_encode_string (strm.str()); - if (!binary_packet.empty()) - return SendPacket (binary_packet.c_str()); - } - return SendPacket ("E85"); - -} - -rnb_err_t RNBRemote::HandlePacket_jThreadExtendedInfo (const char *p) { nub_process_t pid; std::ostringstream json; + std::ostringstream reply_strm; // If we haven't run the process yet, return an error. if (!m_ctx.HasValidProcessID()) { @@ -5184,7 +4996,8 @@ RNBRemote::HandlePacket_jThreadExtendedInfo (const char *p) json << "}"; std::string json_quoted = binary_encode_string (json.str()); - return SendPacket (json_quoted); + reply_strm << json_quoted; + return SendPacket (reply_strm.str()); } } return SendPacket ("OK"); diff --git a/lldb/tools/debugserver/source/RNBRemote.h b/lldb/tools/debugserver/source/RNBRemote.h index 2094c8d82bd..1f4883ab9e0 100644 --- a/lldb/tools/debugserver/source/RNBRemote.h +++ b/lldb/tools/debugserver/source/RNBRemote.h @@ -103,7 +103,6 @@ public: query_gdb_server_version, // 'qGDBServerVersion' query_process_info, // 'qProcessInfo' json_query_thread_extended_info,// 'jThreadExtendedInfo' - json_query_threads_info, // 'jThreadsInfo' pass_signals_to_inferior, // 'QPassSignals' start_noack_mode, // 'QStartNoAckMode' prefix_reg_packets_with_tid, // 'QPrefixRegisterPacketsWithThreadID @@ -191,7 +190,6 @@ public: rnb_err_t HandlePacket_qSyncThreadStateSupported (const char *p); rnb_err_t HandlePacket_qThreadInfo (const char *p); rnb_err_t HandlePacket_jThreadExtendedInfo (const char *p); - rnb_err_t HandlePacket_jThreadsInfo (const char *p); rnb_err_t HandlePacket_qThreadExtraInfo (const char *p); rnb_err_t HandlePacket_qThreadStopInfo (const char *p); rnb_err_t HandlePacket_qHostInfo (const char *p); |

