From 358cf1ea302ebc9c2f307aa710c22821a4ab670a Mon Sep 17 00:00:00 2001 From: Greg Clayton Date: Thu, 25 Jun 2015 21:46:34 +0000 Subject: [PATCH] Resubmitting 240466 after fixing the linux test suite failures. A few extras were fixed - Symbol::GetAddress() now returns an Address object, not a reference. There were places where people were accessing the address of a symbol when the symbol's value wasn't an address symbol. On MacOSX, undefined symbols have a value zero and some places where using the symbol's address and getting an absolute address of zero (since an Address object with no section and an m_offset whose value isn't LLDB_INVALID_ADDRESS is considered an absolute address). So fixing this required some changes to make sure people were getting what they expected. - Since some places want to access the address as a reference, I added a few new functions to symbol: Address &Symbol::GetAddressRef(); const Address &Symbol::GetAddressRef() const; Linux test suite passes just fine now. llvm-svn: 240702 --- lldb/include/lldb/Core/RangeMap.h | 27 +- lldb/include/lldb/Core/StructuredData.h | 89 ++- lldb/include/lldb/Symbol/Symbol.h | 68 ++- lldb/include/lldb/Target/Memory.h | 17 +- lldb/source/API/SBSymbol.cpp | 9 +- lldb/source/API/SBThread.cpp | 4 +- lldb/source/Commands/CommandObjectSource.cpp | 4 +- lldb/source/Commands/CommandObjectTarget.cpp | 15 +- lldb/source/Core/Address.cpp | 6 +- lldb/source/Core/AddressResolverName.cpp | 4 +- lldb/source/Core/Disassembler.cpp | 2 +- lldb/source/Core/FormatEntity.cpp | 2 +- lldb/source/Core/Module.cpp | 5 +- lldb/source/Core/StructuredData.cpp | 4 + lldb/source/Expression/ClangExpressionDeclMap.cpp | 125 ++-- lldb/source/Expression/IRExecutionUnit.cpp | 6 +- lldb/source/Expression/Materializer.cpp | 2 +- .../Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp | 2 +- .../Hexagon-DYLD/HexagonDYLDRendezvous.cpp | 2 +- .../MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp | 14 +- .../AddressSanitizer/AddressSanitizerRuntime.cpp | 4 +- lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp | 6 +- .../ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp | 4 +- .../ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp | 8 +- .../AppleObjCTrampolineHandler.cpp | 14 +- .../RenderScriptRuntime/RenderScriptRuntime.cpp | 8 +- .../Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 4 +- .../Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp | 24 +- .../Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp | 4 +- .../gdb-remote/GDBRemoteCommunicationClient.cpp | 76 ++- .../gdb-remote/GDBRemoteCommunicationClient.h | 7 +- .../Process/gdb-remote/ProcessGDBRemote.cpp | 636 ++++++++++++++------- .../Plugins/Process/gdb-remote/ProcessGDBRemote.h | 19 + .../Plugins/Process/gdb-remote/ThreadGDBRemote.cpp | 7 +- .../Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 2 +- .../SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp | 14 +- .../Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp | 2 +- .../SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp | 6 +- lldb/source/Symbol/ObjectFile.cpp | 2 +- lldb/source/Symbol/Symbol.cpp | 25 +- lldb/source/Symbol/SymbolContext.cpp | 8 +- lldb/source/Symbol/Symtab.cpp | 8 +- lldb/source/Target/Memory.cpp | 139 +++-- lldb/source/Target/Process.cpp | 5 +- lldb/source/Target/ThreadPlanStepRange.cpp | 4 +- .../debugserver.xcodeproj/project.pbxproj | 2 + lldb/tools/debugserver/source/RNBRemote.cpp | 199 ++++++- lldb/tools/debugserver/source/RNBRemote.h | 2 + 48 files changed, 1176 insertions(+), 470 deletions(-) diff --git a/lldb/include/lldb/Core/RangeMap.h b/lldb/include/lldb/Core/RangeMap.h index d78504c..d2c43a5 100644 --- a/lldb/include/lldb/Core/RangeMap.h +++ b/lldb/include/lldb/Core/RangeMap.h @@ -128,9 +128,10 @@ namespace lldb_private { { return Contains(range.GetRangeBase()) && ContainsEndInclusive(range.GetRangeEnd()); } - + + // Returns true if the two ranges adjoing or intersect bool - Overlap (const Range &rhs) const + DoesAdjoinOrIntersect (const Range &rhs) const { const BaseType lhs_base = this->GetRangeBase(); const BaseType rhs_base = rhs.GetRangeBase(); @@ -139,7 +140,19 @@ 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 { @@ -241,7 +254,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->Overlap(*pos)) + if (prev != end && prev->DoesAdjoinOrIntersect(*pos)) { can_combine = true; break; @@ -255,7 +268,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->Overlap(*pos)) + if (prev != end && prev->DoesAdjoinOrIntersect(*pos)) minimal_ranges.back().SetRangeEnd (std::max(prev->GetRangeEnd(), pos->GetRangeEnd())); else minimal_ranges.push_back (*pos); @@ -521,7 +534,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->Overlap(*pos)) + if (prev != end && prev->DoesAdjoinOrIntersect(*pos)) { can_combine = true; break; @@ -535,7 +548,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->Overlap(*pos)) + if (prev != end && prev->DoesAdjoinOrIntersect(*pos)) minimal_ranges.back().SetRangeEnd (std::max(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 9a54fb3..8acfa31 100644 --- a/lldb/include/lldb/Core/StructuredData.h +++ b/lldb/include/lldb/Core/StructuredData.h @@ -13,10 +13,11 @@ // C Includes // C++ Includes +#include #include +#include #include #include -#include #include "llvm/ADT/StringRef.h" @@ -140,6 +141,15 @@ public: return NULL; } + uint64_t + GetIntegerValue (uint64_t fail_value = 0) + { + Integer *integer = GetAsInteger (); + if (integer) + return integer->GetValue(); + return fail_value; + } + Float * GetAsFloat () { @@ -148,6 +158,15 @@ public: return NULL; } + double + GetFloatValue (double fail_value = 0.0) + { + Float *f = GetAsFloat (); + if (f) + return f->GetValue(); + return fail_value; + } + Boolean * GetAsBoolean () { @@ -156,6 +175,15 @@ public: return NULL; } + bool + GetBooleanValue (bool fail_value = false) + { + Boolean *b = GetAsBoolean (); + if (b) + return b->GetValue(); + return fail_value; + } + String * GetAsString () { @@ -164,6 +192,19 @@ 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() { @@ -197,6 +238,17 @@ public: { } + void + ForEach (std::function const &foreach_callback) const + { + for (const auto &object_sp : m_items) + { + if (foreach_callback(object_sp.get()) == false) + break; + } + } + + size_t GetSize() const { @@ -447,7 +499,7 @@ public: m_value = string; } - std::string + const std::string & GetValue () { return m_value; @@ -462,6 +514,7 @@ public: class Dictionary : public Object { public: + Dictionary () : Object (Type::eTypeDictionary), m_dict () @@ -478,6 +531,16 @@ public: return m_dict.size(); } + void + ForEach (std::function const &callback) const + { + for (const auto &pair : m_dict) + { + if (callback (pair.first, pair.second.get()) == false) + break; + } + } + ObjectSP GetKeys() const { @@ -628,33 +691,25 @@ public: void AddIntegerItem (llvm::StringRef key, uint64_t value) { - ObjectSP val_obj (new Integer()); - val_obj->GetAsInteger()->SetValue (value); - AddItem (key, val_obj); + AddItem (key, ObjectSP (new Integer(value))); } void AddFloatItem (llvm::StringRef key, double value) { - ObjectSP val_obj (new Float()); - val_obj->GetAsFloat()->SetValue (value); - AddItem (key, val_obj); + AddItem (key, ObjectSP (new Float(value))); } void AddStringItem (llvm::StringRef key, std::string value) { - ObjectSP val_obj (new String()); - val_obj->GetAsString()->SetValue (value); - AddItem (key, val_obj); + AddItem (key, ObjectSP (new String(std::move(value)))); } void AddBooleanItem (llvm::StringRef key, bool value) { - ObjectSP val_obj (new Boolean()); - val_obj->GetAsBoolean()->SetValue (value); - AddItem (key, val_obj); + AddItem (key, ObjectSP (new Boolean(value))); } void Dump(Stream &s) const override; @@ -690,9 +745,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/Symbol/Symbol.h b/lldb/include/lldb/Symbol/Symbol.h index 6e14dff..ad11563 100644 --- a/lldb/include/lldb/Symbol/Symbol.h +++ b/lldb/include/lldb/Symbol/Symbol.h @@ -72,25 +72,81 @@ public: ValueIsAddress() const; //------------------------------------------------------------------ - // Access the address value. Do NOT hand out the AddressRange as an - // object as the byte size of the address range may not be filled in - // and it should be accessed via GetByteSize(). + // The GetAddressRef() accessor functions should only be called if + // you previously call ValueIsAddress() otherwise you might get an + // reference to an Address object that contains an constant integer + // value in m_addr_range.m_base_addr.m_offset which could be + // incorrectly used to represent an absolute address since it has + // no section. //------------------------------------------------------------------ Address & - GetAddress() + GetAddressRef() { return m_addr_range.GetBaseAddress(); } + const Address & + GetAddressRef() const + { + return m_addr_range.GetBaseAddress(); + } + + //------------------------------------------------------------------ + // Makes sure the symbol's value is an address and returns the file + // address. Returns LLDB_INVALID_ADDRESS if the symbol's value isn't + // an address. + //------------------------------------------------------------------ + lldb::addr_t + GetFileAddress () const; + + //------------------------------------------------------------------ + // Makes sure the symbol's value is an address and gets the load + // address using \a target if it is. Returns LLDB_INVALID_ADDRESS + // if the symbol's value isn't an address or if the section isn't + // loaded in \a target. + //------------------------------------------------------------------ + lldb::addr_t + GetLoadAddress (Target *target) const; + //------------------------------------------------------------------ // Access the address value. Do NOT hand out the AddressRange as an // object as the byte size of the address range may not be filled in // and it should be accessed via GetByteSize(). //------------------------------------------------------------------ - const Address & + Address GetAddress() const { - return m_addr_range.GetBaseAddress(); + // Make sure the our value is an address before we hand a copy out. + // We use the Address inside m_addr_range to contain the value for + // symbols that are not address based symbols so we are using it + // for more than just addresses. For example undefined symbols on + // MacOSX have a nlist.n_value of 0 (zero) and this will get placed + // into m_addr_range.m_base_addr.m_offset and it will have no section. + // So in the GetAddress() accessor, we need to hand out an invalid + // address if the symbol's value isn't an address. + if (ValueIsAddress()) + return m_addr_range.GetBaseAddress(); + else + return Address(); + } + + // When a symbol's value isn't an address, we need to access the raw + // value. This function will ensure this symbol's value isn't an address + // and return the integer value if this checks out, otherwise it will + // return "fail_value" if the symbol is an address value. + uint64_t + GetIntegerValue (uint64_t fail_value = 0) const + { + if (ValueIsAddress()) + { + // This symbol's value is an address. Use Symbol::GetAddress() to get the address. + return fail_value; + } + else + { + // The value is stored in the base address' offset + return m_addr_range.GetBaseAddress().GetOffset(); + } } lldb::addr_t diff --git a/lldb/include/lldb/Target/Memory.h b/lldb/include/lldb/Target/Memory.h index 568bbcd..bf1cc18 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_cache_line_byte_size ; + return m_L2_cache_line_byte_size ; } void @@ -61,17 +61,26 @@ 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 BlockMap; typedef RangeArray InvalidRanges; + typedef Range 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_cache; + 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) 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/SBSymbol.cpp b/lldb/source/API/SBSymbol.cpp index 12a3b31..246a455 100644 --- a/lldb/source/API/SBSymbol.cpp +++ b/lldb/source/API/SBSymbol.cpp @@ -137,10 +137,11 @@ SBSymbol::GetInstructions (SBTarget target, const char *flavor_string) } if (m_opaque_ptr->ValueIsAddress()) { - ModuleSP module_sp (m_opaque_ptr->GetAddress().GetModule()); + const Address &symbol_addr = m_opaque_ptr->GetAddressRef(); + ModuleSP module_sp = symbol_addr.GetModule(); if (module_sp) { - AddressRange symbol_range (m_opaque_ptr->GetAddress(), m_opaque_ptr->GetByteSize()); + AddressRange symbol_range (symbol_addr, m_opaque_ptr->GetByteSize()); const bool prefer_file_cache = false; sb_instructions.SetDisassembler (Disassembler::DisassembleRange (module_sp->GetArchitecture (), NULL, @@ -172,7 +173,7 @@ SBSymbol::GetStartAddress () SBAddress addr; if (m_opaque_ptr && m_opaque_ptr->ValueIsAddress()) { - addr.SetAddress (&m_opaque_ptr->GetAddress()); + addr.SetAddress (&m_opaque_ptr->GetAddressRef()); } return addr; } @@ -186,7 +187,7 @@ SBSymbol::GetEndAddress () lldb::addr_t range_size = m_opaque_ptr->GetByteSize(); if (range_size > 0) { - addr.SetAddress (&m_opaque_ptr->GetAddress()); + addr.SetAddress (&m_opaque_ptr->GetAddressRef()); addr->Slide (m_opaque_ptr->GetByteSize()); } } diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp index 78f57f5..dfc7ce9 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)::GetQueueKind() => error: process is running", + log->Printf ("SBThread(%p)::GetQueue() => error: process is running", static_cast(exe_ctx.GetThreadPtr())); } } if (log) - log->Printf ("SBThread(%p)::GetQueueKind () => SBQueue(%p)", + log->Printf ("SBThread(%p)::GetQueue () => SBQueue(%p)", static_cast(exe_ctx.GetThreadPtr()), static_cast(queue_sp.get())); return sb_queue; diff --git a/lldb/source/Commands/CommandObjectSource.cpp b/lldb/source/Commands/CommandObjectSource.cpp index e30aeca..7c5f127 100644 --- a/lldb/source/Commands/CommandObjectSource.cpp +++ b/lldb/source/Commands/CommandObjectSource.cpp @@ -537,9 +537,9 @@ protected: { SymbolContext sc; sc_list_symbols.GetContextAtIndex (i, sc); - if (sc.symbol) + if (sc.symbol && sc.symbol->ValueIsAddress()) { - const Address &base_address = sc.symbol->GetAddress(); + const Address &base_address = sc.symbol->GetAddressRef(); Function *function = base_address.CalculateSymbolContextFunction(); if (function) { diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index 864055d..7257ff3 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -1734,17 +1734,16 @@ LookupSymbolInModule (CommandInterpreter &interpreter, Stream &strm, Module *mod DumpFullpath (strm, &module->GetFileSpec(), 0); strm.PutCString(":\n"); strm.IndentMore (); - //Symtab::DumpSymbolHeader (&strm); for (i=0; i < num_matches; ++i) { Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]); - DumpAddress (interpreter.GetExecutionContext().GetBestExecutionContextScope(), - symbol->GetAddress(), - verbose, - strm); - -// strm.Indent (); -// symbol->Dump (&strm, interpreter.GetExecutionContext().GetTargetPtr(), i); + if (symbol && symbol->ValueIsAddress()) + { + DumpAddress (interpreter.GetExecutionContext().GetBestExecutionContextScope(), + symbol->GetAddressRef(), + verbose, + strm); + } } strm.IndentLess (); return num_matches; diff --git a/lldb/source/Core/Address.cpp b/lldb/source/Core/Address.cpp index 6d4e2ff..1cd7a74 100644 --- a/lldb/source/Core/Address.cpp +++ b/lldb/source/Core/Address.cpp @@ -501,7 +501,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum if (symbol_name) { s->PutCString(symbol_name); - addr_t delta = file_Addr - symbol->GetAddress().GetFileAddress(); + addr_t delta = file_Addr - symbol->GetAddressRef().GetFileAddress(); if (delta) s->Printf(" + %" PRIu64, delta); showed_info = true; @@ -669,7 +669,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum // If we have just a symbol make sure it is in the right section if (sc.symbol->ValueIsAddress()) { - if (sc.symbol->GetAddress().GetSection() != GetSection()) + if (sc.symbol->GetAddressRef().GetSection() != GetSection()) { // don't show the module if the symbol is a trampoline symbol show_stop_context = false; @@ -722,7 +722,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum // as our address. If it isn't, then we might have just found // the last symbol that came before the address that we are // looking up that has nothing to do with our address lookup. - if (sc.symbol->ValueIsAddress() && sc.symbol->GetAddress().GetSection() != GetSection()) + if (sc.symbol->ValueIsAddress() && sc.symbol->GetAddressRef().GetSection() != GetSection()) sc.symbol = NULL; } sc.GetDescription(s, eDescriptionLevelBrief, target); diff --git a/lldb/source/Core/AddressResolverName.cpp b/lldb/source/Core/AddressResolverName.cpp index d47fa1e..1c6205f 100644 --- a/lldb/source/Core/AddressResolverName.cpp +++ b/lldb/source/Core/AddressResolverName.cpp @@ -165,7 +165,7 @@ AddressResolverName::SearchCallback { if (symbol_sc.symbol && symbol_sc.symbol->ValueIsAddress()) { - if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddress()) + if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRef()) { sym_list.RemoveContextAtIndex(j); continue; // Don't increment j @@ -211,7 +211,7 @@ AddressResolverName::SearchCallback { if (sc.symbol && sc.symbol->ValueIsAddress()) { - func_addr = sc.symbol->GetAddress(); + func_addr = sc.symbol->GetAddressRef(); addr_t byte_size = sc.symbol->GetByteSize(); if (skip_prologue) diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp index edfc49b..f96232f 100644 --- a/lldb/source/Core/Disassembler.cpp +++ b/lldb/source/Core/Disassembler.cpp @@ -548,7 +548,7 @@ Disassembler::Disassemble } else if (sc.symbol && sc.symbol->ValueIsAddress()) { - range.GetBaseAddress() = sc.symbol->GetAddress(); + range.GetBaseAddress() = sc.symbol->GetAddressRef(); range.SetByteSize (sc.symbol->GetByteSize()); } else diff --git a/lldb/source/Core/FormatEntity.cpp b/lldb/source/Core/FormatEntity.cpp index 1dec0bf..2ebe957 100644 --- a/lldb/source/Core/FormatEntity.cpp +++ b/lldb/source/Core/FormatEntity.cpp @@ -477,7 +477,7 @@ DumpAddressOffsetFromFunction (Stream &s, } } else if (sc->symbol && sc->symbol->ValueIsAddress()) - func_addr = sc->symbol->GetAddress(); + func_addr = sc->symbol->GetAddressRef(); } if (func_addr.IsValid()) diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index 6696597..eb0359d 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -902,10 +902,9 @@ Module::FindFunctions (const RegularExpression& regex, { sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); SymbolType sym_type = sc.symbol->GetType(); - if (sc.symbol && (sym_type == eSymbolTypeCode || - sym_type == eSymbolTypeResolver)) + if (sc.symbol && sc.symbol->ValueIsAddress() && (sym_type == eSymbolTypeCode || sym_type == eSymbolTypeResolver)) { - FileAddrToIndexMap::const_iterator pos = file_addr_to_index.find(sc.symbol->GetAddress().GetFileAddress()); + FileAddrToIndexMap::const_iterator pos = file_addr_to_index.find(sc.symbol->GetAddressRef().GetFileAddress()); if (pos == end) sc_list.Append(sc); else diff --git a/lldb/source/Core/StructuredData.cpp b/lldb/source/Core/StructuredData.cpp index 9286c3a..a2c4409 100644 --- a/lldb/source/Core/StructuredData.cpp +++ b/lldb/source/Core/StructuredData.cpp @@ -298,6 +298,10 @@ 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/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Expression/ClangExpressionDeclMap.cpp index 42a7d76..1013bb5 100644 --- a/lldb/source/Expression/ClangExpressionDeclMap.cpp +++ b/lldb/source/Expression/ClangExpressionDeclMap.cpp @@ -665,74 +665,71 @@ ClangExpressionDeclMap::GetSymbolAddress (Target &target, SymbolContext sym_ctx; sc_list.GetContextAtIndex(i, sym_ctx); - const Address *sym_address = &sym_ctx.symbol->GetAddress(); + const Address sym_address = sym_ctx.symbol->GetAddress(); - if (!sym_address || !sym_address->IsValid()) + if (!sym_address.IsValid()) continue; - if (sym_address) + switch (sym_ctx.symbol->GetType()) { - switch (sym_ctx.symbol->GetType()) - { - case eSymbolTypeCode: - case eSymbolTypeTrampoline: - symbol_load_addr = sym_address->GetCallableLoadAddress (&target); - break; + case eSymbolTypeCode: + case eSymbolTypeTrampoline: + symbol_load_addr = sym_address.GetCallableLoadAddress (&target); + break; - case eSymbolTypeResolver: - symbol_load_addr = sym_address->GetCallableLoadAddress (&target, true); - break; + case eSymbolTypeResolver: + symbol_load_addr = sym_address.GetCallableLoadAddress (&target, true); + break; - case eSymbolTypeReExported: + case eSymbolTypeReExported: + { + ConstString reexport_name = sym_ctx.symbol->GetReExportedSymbolName(); + if (reexport_name) { - ConstString reexport_name = sym_ctx.symbol->GetReExportedSymbolName(); - if (reexport_name) + ModuleSP reexport_module_sp; + ModuleSpec reexport_module_spec; + reexport_module_spec.GetPlatformFileSpec() = sym_ctx.symbol->GetReExportedSymbolSharedLibrary(); + if (reexport_module_spec.GetPlatformFileSpec()) { - ModuleSP reexport_module_sp; - ModuleSpec reexport_module_spec; - reexport_module_spec.GetPlatformFileSpec() = sym_ctx.symbol->GetReExportedSymbolSharedLibrary(); - if (reexport_module_spec.GetPlatformFileSpec()) + reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); + if (!reexport_module_sp) { + reexport_module_spec.GetPlatformFileSpec().GetDirectory().Clear(); reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); - if (!reexport_module_sp) - { - reexport_module_spec.GetPlatformFileSpec().GetDirectory().Clear(); - reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); - } } - symbol_load_addr = GetSymbolAddress(target, process, sym_ctx.symbol->GetReExportedSymbolName(), symbol_type, reexport_module_sp.get()); } + symbol_load_addr = GetSymbolAddress(target, process, sym_ctx.symbol->GetReExportedSymbolName(), symbol_type, reexport_module_sp.get()); } - break; - - case eSymbolTypeData: - case eSymbolTypeRuntime: - case eSymbolTypeVariable: - case eSymbolTypeLocal: - case eSymbolTypeParam: - case eSymbolTypeInvalid: - case eSymbolTypeAbsolute: - case eSymbolTypeException: - case eSymbolTypeSourceFile: - case eSymbolTypeHeaderFile: - case eSymbolTypeObjectFile: - case eSymbolTypeCommonBlock: - case eSymbolTypeBlock: - case eSymbolTypeVariableType: - case eSymbolTypeLineEntry: - case eSymbolTypeLineHeader: - case eSymbolTypeScopeBegin: - case eSymbolTypeScopeEnd: - case eSymbolTypeAdditional: - case eSymbolTypeCompiler: - case eSymbolTypeInstrumentation: - case eSymbolTypeUndefined: - case eSymbolTypeObjCClass: - case eSymbolTypeObjCMetaClass: - case eSymbolTypeObjCIVar: - symbol_load_addr = sym_address->GetLoadAddress (&target); - break; - } + } + break; + + case eSymbolTypeData: + case eSymbolTypeRuntime: + case eSymbolTypeVariable: + case eSymbolTypeLocal: + case eSymbolTypeParam: + case eSymbolTypeInvalid: + case eSymbolTypeAbsolute: + case eSymbolTypeException: + case eSymbolTypeSourceFile: + case eSymbolTypeHeaderFile: + case eSymbolTypeObjectFile: + case eSymbolTypeCommonBlock: + case eSymbolTypeBlock: + case eSymbolTypeVariableType: + case eSymbolTypeLineEntry: + case eSymbolTypeLineHeader: + case eSymbolTypeScopeBegin: + case eSymbolTypeScopeEnd: + case eSymbolTypeAdditional: + case eSymbolTypeCompiler: + case eSymbolTypeInstrumentation: + case eSymbolTypeUndefined: + case eSymbolTypeObjCClass: + case eSymbolTypeObjCMetaClass: + case eSymbolTypeObjCIVar: + symbol_load_addr = sym_address.GetLoadAddress (&target); + break; } } @@ -780,9 +777,9 @@ ClangExpressionDeclMap::FindGlobalDataSymbol (Target &target, if (sym_ctx.symbol) { const Symbol *symbol = sym_ctx.symbol; - const Address *sym_address = &symbol->GetAddress(); + const Address sym_address = symbol->GetAddress(); - if (sym_address && sym_address->IsValid()) + if (sym_address.IsValid()) { switch (symbol->GetType()) { @@ -1818,7 +1815,7 @@ ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context, entity->EnableParserVars(GetParserID()); ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); - const Address &symbol_address = symbol.GetAddress(); + const Address symbol_address = symbol.GetAddress(); lldb::addr_t symbol_load_addr = symbol_address.GetLoadAddress(target); //parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, user_type.GetOpaqueQualType()); @@ -1957,7 +1954,7 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); NamedDecl *function_decl = NULL; - const Address *fun_address = NULL; + Address fun_address; ClangASTType function_clang_type; bool is_indirect_function = false; @@ -1982,7 +1979,7 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, return; } - fun_address = &function->GetAddressRange().GetBaseAddress(); + fun_address = function->GetAddressRange().GetBaseAddress(); ClangASTType copied_function_type = GuardedCopyType(function_clang_type); if (copied_function_type) @@ -2016,7 +2013,7 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, } else if (symbol) { - fun_address = &symbol->GetAddress(); + fun_address = symbol->GetAddress(); function_decl = context.AddGenericFunDecl(); is_indirect_function = symbol->IsIndirect(); } @@ -2029,7 +2026,7 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - lldb::addr_t load_addr = fun_address->GetCallableLoadAddress(target, is_indirect_function); + lldb::addr_t load_addr = fun_address.GetCallableLoadAddress(target, is_indirect_function); ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (), m_parser_vars->m_target_info.byte_order, @@ -2052,7 +2049,7 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, { // We have to try finding a file address. - lldb::addr_t file_addr = fun_address->GetFileAddress(); + lldb::addr_t file_addr = fun_address.GetFileAddress(); parser_vars->m_lldb_value.SetValueType(Value::eValueTypeFileAddress); parser_vars->m_lldb_value.GetScalar() = file_addr; @@ -2068,7 +2065,7 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, StreamString ss; - fun_address->Dump(&ss, m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription); + fun_address.Dump(&ss, m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription); log->Printf(" CEDM::FEVD[%u] Found %s function %s (description %s), returned %s", current_id, diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index e0308c2..96fedae 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -679,16 +679,16 @@ IRExecutionUnit::MemoryManager::getSymbolAddress(const std::string &Name) if (sym_ctx.symbol->GetType() == lldb::eSymbolTypeUndefined) continue; - const Address *sym_address = &sym_ctx.symbol->GetAddress(); + const Address sym_address = sym_ctx.symbol->GetAddress(); - if (!sym_address || !sym_address->IsValid()) + if (!sym_address.IsValid()) continue; symbol_load_addr = sym_ctx.symbol->ResolveCallableAddress(*target_sp); if (symbol_load_addr == LLDB_INVALID_ADDRESS) { - symbol_load_addr = sym_ctx.symbol->GetAddress().GetLoadAddress(target_sp.get()); + symbol_load_addr = sym_address.GetLoadAddress(target_sp.get()); } } diff --git a/lldb/source/Expression/Materializer.cpp b/lldb/source/Expression/Materializer.cpp index 809b812..ef01fee 100644 --- a/lldb/source/Expression/Materializer.cpp +++ b/lldb/source/Expression/Materializer.cpp @@ -1052,7 +1052,7 @@ public: m_symbol.GetName().AsCString()); } - Address &sym_address = m_symbol.GetAddress(); + const Address sym_address = m_symbol.GetAddress(); ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); diff --git a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp index 061283b..87dadd7 100644 --- a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp @@ -64,7 +64,7 @@ static lldb::addr_t findSymbolAddress( Process *proc, ConstString findName ) if ( ConstString::Compare( findName, symName ) == 0 ) { - Address addr = sym->GetAddress( ); + Address addr = sym->GetAddressObj( ); return addr.GetLoadAddress( & proc->GetTarget() ); } } diff --git a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp index 61f9b3d..5b9c39d 100644 --- a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp +++ b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp @@ -332,7 +332,7 @@ HexagonDYLDRendezvous::FindMetadata(const char *name, PThreadField field, uint32 if (!target.GetImages().FindSymbolsWithNameAndType (ConstString(name), eSymbolTypeAny, list)) return false; - Address address = list[0].symbol->GetAddress(); + Address address = list[0].symbol->GetAddressObj(); addr_t addr = address.GetLoadAddress (&target); if (addr == LLDB_INVALID_ADDRESS) return false; diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp index 80fe253..33a375f 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp @@ -407,7 +407,7 @@ DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb:: static ConstString g_dyld_all_image_infos ("dyld_all_image_infos"); const Symbol *symbol = dyld_module_sp->FindFirstSymbolWithNameAndType (g_dyld_all_image_infos, eSymbolTypeData); if (symbol) - m_dyld_all_image_infos_addr = symbol->GetAddress().GetLoadAddress(&target); + m_dyld_all_image_infos_addr = symbol->GetLoadAddress(&target); } // Update all image infos @@ -1370,7 +1370,7 @@ DynamicLoaderMacOSXDYLD::AlwaysRelyOnEHUnwindInfo (SymbolContext &sym_ctx) ModuleSP module_sp; if (sym_ctx.symbol) { - module_sp = sym_ctx.symbol->GetAddress().GetModule(); + module_sp = sym_ctx.symbol->GetAddressRef().GetModule(); } if (module_sp.get() == NULL && sym_ctx.function) { @@ -1649,12 +1649,13 @@ DynamicLoaderMacOSXDYLD::GetStepThroughTrampolinePlan (Thread &thread, bool stop Symbol *actual_symbol = context.symbol->ResolveReExportedSymbol(*target_sp.get()); if (actual_symbol) { - if (actual_symbol->GetAddress().IsValid()) + const Address actual_symbol_addr = actual_symbol->GetAddress(); + if (actual_symbol_addr.IsValid()) { - addresses.push_back(actual_symbol->GetAddress()); + addresses.push_back(actual_symbol_addr); if (log) { - lldb::addr_t load_addr = actual_symbol->GetAddress().GetLoadAddress(target_sp.get()); + lldb::addr_t load_addr = actual_symbol_addr.GetLoadAddress(target_sp.get()); log->Printf ("Found a re-exported symbol: %s at 0x%" PRIx64 ".", actual_symbol->GetName().GetCString(), load_addr); } @@ -1720,7 +1721,8 @@ DynamicLoaderMacOSXDYLD::GetStepThroughTrampolinePlan (Thread &thread, bool stop if (symbol && symbol->IsIndirect()) { Error error; - addr_t resolved_addr = thread.GetProcess()->ResolveIndirectFunction(&symbol->GetAddress(), error); + Address symbol_address = symbol->GetAddress(); + addr_t resolved_addr = thread.GetProcess()->ResolveIndirectFunction(&symbol_address, error); if (error.Success()) { load_addrs.push_back(resolved_addr); diff --git a/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp b/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp index 54c6834..9b72ceb 100644 --- a/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp +++ b/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp @@ -287,11 +287,11 @@ AddressSanitizerRuntime::Activate() if (symbol == NULL) return; - if (!symbol->GetAddress().IsValid()) + if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid()) return; Target &target = m_process->GetTarget(); - addr_t symbol_address = symbol->GetAddress().GetOpcodeLoadAddress(&target); + addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target); if (symbol_address == LLDB_INVALID_ADDRESS) return; diff --git a/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp b/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp index b9c71ad..8e454e7 100644 --- a/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp +++ b/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp @@ -436,10 +436,10 @@ JITLoaderGDB::GetSymbolAddress(ModuleList &module_list, const ConstString &name, SymbolContext sym_ctx; target_symbols.GetContextAtIndex(0, sym_ctx); - const Address *jit_descriptor_addr = &sym_ctx.symbol->GetAddress(); - if (!jit_descriptor_addr || !jit_descriptor_addr->IsValid()) + const Address jit_descriptor_addr = sym_ctx.symbol->GetAddress(); + if (!jit_descriptor_addr.IsValid()) return LLDB_INVALID_ADDRESS; - const addr_t jit_addr = jit_descriptor_addr->GetLoadAddress(&target); + const addr_t jit_addr = jit_descriptor_addr.GetLoadAddress(&target); return jit_addr; } diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp index 792886f..9f0f6aa 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp @@ -299,13 +299,13 @@ AppleObjCRuntimeV1::GetISAHashTablePointer () static ConstString g_objc_debug_class_hash("_objc_debug_class_hash"); const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(g_objc_debug_class_hash, lldb::eSymbolTypeData); - if (symbol) + if (symbol && symbol->ValueIsAddress()) { Process *process = GetProcess(); if (process) { - lldb::addr_t objc_debug_class_hash_addr = symbol->GetAddress().GetLoadAddress(&process->GetTarget()); + lldb::addr_t objc_debug_class_hash_addr = symbol->GetAddressRef().GetLoadAddress(&process->GetTarget()); if (objc_debug_class_hash_addr != LLDB_INVALID_ADDRESS) { diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 02d9350b..54a253c 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -321,9 +321,9 @@ ExtractRuntimeGlobalSymbol (Process* process, if (!byte_size) byte_size = process->GetAddressByteSize(); const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType(name, lldb::eSymbolTypeData); - if (symbol) + if (symbol && symbol->ValueIsAddress()) { - lldb::addr_t symbol_load_addr = symbol->GetAddress().GetLoadAddress(&process->GetTarget()); + lldb::addr_t symbol_load_addr = symbol->GetAddressRef().GetLoadAddress(&process->GetTarget()); if (symbol_load_addr != LLDB_INVALID_ADDRESS) { if (read_value) @@ -815,7 +815,7 @@ AppleObjCRuntimeV2::GetByteOffsetForIvar (ClangASTType &parent_ast_type, const c if (sc_list.GetSize() == 1 && sc_list.GetContextAtIndex(0, ivar_offset_symbol)) { if (ivar_offset_symbol.symbol) - ivar_offset_address = ivar_offset_symbol.symbol->GetAddress().GetLoadAddress (&target); + ivar_offset_address = ivar_offset_symbol.symbol->GetLoadAddress (&target); } //---------------------------------------------------------------------- @@ -1191,7 +1191,7 @@ AppleObjCRuntimeV2::GetISAHashTablePointer () const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_objc_realized_classes, lldb::eSymbolTypeAny); if (symbol) { - lldb::addr_t gdb_objc_realized_classes_ptr = symbol->GetAddress().GetLoadAddress(&process->GetTarget()); + lldb::addr_t gdb_objc_realized_classes_ptr = symbol->GetLoadAddress(&process->GetTarget()); if (gdb_objc_realized_classes_ptr != LLDB_INVALID_ADDRESS) { diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp index dd2d0e0..5d82f16 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp @@ -471,10 +471,7 @@ AppleObjCTrampolineHandler::AppleObjCVTables::InitializeVTableSymbols () eSymbolTypeData); if (trampoline_symbol != NULL) { - if (!trampoline_symbol->GetAddress().IsValid()) - return false; - - m_trampoline_header = trampoline_symbol->GetAddress().GetLoadAddress(&target); + m_trampoline_header = trampoline_symbol->GetLoadAddress(&target); if (m_trampoline_header == LLDB_INVALID_ADDRESS) return false; @@ -484,10 +481,11 @@ AppleObjCTrampolineHandler::AppleObjCVTables::InitializeVTableSymbols () eSymbolTypeCode); if (changed_symbol != NULL) { - if (!changed_symbol->GetAddress().IsValid()) + const Address changed_symbol_addr = changed_symbol->GetAddress(); + if (!changed_symbol_addr.IsValid()) return false; - lldb::addr_t changed_addr = changed_symbol->GetAddress().GetOpcodeLoadAddress (&target); + lldb::addr_t changed_addr = changed_symbol_addr.GetOpcodeLoadAddress (&target); if (changed_addr != LLDB_INVALID_ADDRESS) { BreakpointSP trampolines_changed_bp_sp = target.CreateBreakpoint (changed_addr, true, false); @@ -703,13 +701,13 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler (const ProcessSP &process { ConstString name_const_str(g_dispatch_functions[i].name); const Symbol *msgSend_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (name_const_str, eSymbolTypeCode); - if (msgSend_symbol) + if (msgSend_symbol && msgSend_symbol->ValueIsAddress()) { // FixMe: Make g_dispatch_functions static table of DispatchFunctions, and have the map be address->index. // Problem is we also need to lookup the dispatch function. For now we could have a side table of stret & non-stret // dispatch functions. If that's as complex as it gets, we're fine. - lldb::addr_t sym_addr = msgSend_symbol->GetAddress().GetOpcodeLoadAddress(target); + lldb::addr_t sym_addr = msgSend_symbol->GetAddressRef().GetOpcodeLoadAddress(target); m_msgSend_map.insert(std::pair(sym_addr, i)); } diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp index da36b19..2490cf3 100644 --- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp @@ -422,7 +422,7 @@ RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind) const Symbol *sym = module->FindFirstSymbolWithNameAndType(ConstString(hook_defn->symbol_name), eSymbolTypeCode); - addr_t addr = sym->GetAddress().GetLoadAddress(&target); + addr_t addr = sym->GetLoadAddress(&target); if (addr == LLDB_INVALID_ADDRESS) { if(log) @@ -542,7 +542,7 @@ RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) Error error; uint32_t flag = 0x00000001U; Target &target = GetProcess()->GetTarget(); - addr_t addr = debug_present->GetAddress().GetLoadAddress(&target); + addr_t addr = debug_present->GetLoadAddress(&target); GetProcess()->WriteMemory(addr, &flag, sizeof(flag), error); if(error.Success()) { @@ -597,7 +597,7 @@ RSModuleDescriptor::ParseRSInfo() const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData); if (info_sym) { - const addr_t addr = info_sym->GetAddress().GetFileAddress(); + const addr_t addr = info_sym->GetAddressRef().GetFileAddress(); const addr_t size = info_sym->GetByteSize(); const FileSpec fs = m_module->GetFileSpec(); @@ -809,7 +809,7 @@ RenderScriptRuntime::AttemptBreakpointAtKernelName(Stream &strm, const char* nam } } - addr_t bp_addr = kernel_sym->GetAddress().GetLoadAddress(&GetProcess()->GetTarget()); + addr_t bp_addr = kernel_sym->GetLoadAddress(&GetProcess()->GetTarget()); if (bp_addr == LLDB_INVALID_ADDRESS) { error.SetErrorStringWithFormat("Could not locate load address for symbols of kernel '%s'.", name); diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index bdc13e7..1ceaa2c 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -2381,7 +2381,7 @@ ObjectFileELF::RelocateSection(Symtab* symtab, const ELFHeader *hdr, const ELFSe symbol = symtab->FindSymbolByID(reloc_symbol(rel)); if (symbol) { - addr_t value = symbol->GetAddress().GetFileAddress(); + addr_t value = symbol->GetAddressRef().GetFileAddress(); DataBufferSP& data_buffer_sp = debug_data.GetSharedDataBuffer(); uint64_t* dst = reinterpret_cast(data_buffer_sp->GetBytes() + rel_section->GetFileOffset() + ELFRelocation::RelocOffset64(rel)); *dst = value + ELFRelocation::RelocAddend64(rel); @@ -2394,7 +2394,7 @@ ObjectFileELF::RelocateSection(Symtab* symtab, const ELFHeader *hdr, const ELFSe symbol = symtab->FindSymbolByID(reloc_symbol(rel)); if (symbol) { - addr_t value = symbol->GetAddress().GetFileAddress(); + addr_t value = symbol->GetAddressRef().GetFileAddress(); value += ELFRelocation::RelocAddend32(rel); assert((reloc_type(rel) == R_X86_64_32 && (value <= UINT32_MAX)) || (reloc_type(rel) == R_X86_64_32S && diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index c61f871..511d73d 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -1271,7 +1271,7 @@ ObjectFileMachO::GetAddressClass (lldb::addr_t file_addr) { if (symbol->ValueIsAddress()) { - SectionSP section_sp (symbol->GetAddress().GetSection()); + SectionSP section_sp (symbol->GetAddressRef().GetSection()); if (section_sp) { const lldb::SectionType section_type = section_sp->GetType(); @@ -3521,8 +3521,8 @@ ObjectFileMachO::ParseSymtab () m_nlist_idx_to_sym_idx[nlist_idx] = GSYM_sym_idx; // Copy the address, because often the N_GSYM address has an invalid address of zero // when the global is a common symbol - sym[GSYM_sym_idx].GetAddress().SetSection (symbol_section); - sym[GSYM_sym_idx].GetAddress().SetOffset (symbol_value); + sym[GSYM_sym_idx].GetAddressRef().SetSection (symbol_section); + sym[GSYM_sym_idx].GetAddressRef().SetOffset (symbol_value); // We just need the flags from the linker symbol, so put these flags // into the N_GSYM flags to avoid duplicate symbols in the symbol table sym[GSYM_sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc); @@ -3537,8 +3537,8 @@ ObjectFileMachO::ParseSymtab () sym[sym_idx].SetType (type); if (set_value) { - sym[sym_idx].GetAddress().SetSection (symbol_section); - sym[sym_idx].GetAddress().SetOffset (symbol_value); + sym[sym_idx].GetAddressRef().SetSection (symbol_section); + sym[sym_idx].GetAddressRef().SetOffset (symbol_value); } sym[sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc); @@ -4364,8 +4364,8 @@ ObjectFileMachO::ParseSymtab () m_nlist_idx_to_sym_idx[nlist_idx] = GSYM_sym_idx; // Copy the address, because often the N_GSYM address has an invalid address of zero // when the global is a common symbol - sym[GSYM_sym_idx].GetAddress().SetSection (symbol_section); - sym[GSYM_sym_idx].GetAddress().SetOffset (symbol_value); + sym[GSYM_sym_idx].GetAddressRef().SetSection (symbol_section); + sym[GSYM_sym_idx].GetAddressRef().SetOffset (symbol_value); // We just need the flags from the linker symbol, so put these flags // into the N_GSYM flags to avoid duplicate symbols in the symbol table sym[GSYM_sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc); @@ -4380,8 +4380,8 @@ ObjectFileMachO::ParseSymtab () sym[sym_idx].SetType (type); if (set_value) { - sym[sym_idx].GetAddress().SetSection (symbol_section); - sym[sym_idx].GetAddress().SetOffset (symbol_value); + sym[sym_idx].GetAddressRef().SetSection (symbol_section); + sym[sym_idx].GetAddressRef().SetOffset (symbol_value); } sym[sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc); @@ -4475,7 +4475,7 @@ ObjectFileMachO::ParseSymtab () sym[sym_idx].GetMangled().SetDemangledName(ConstString(synthetic_function_symbol)); sym[sym_idx].SetType (eSymbolTypeCode); sym[sym_idx].SetIsSynthetic (true); - sym[sym_idx].GetAddress() = symbol_addr; + sym[sym_idx].GetAddressRef() = symbol_addr; if (symbol_flags) sym[sym_idx].SetFlags (symbol_flags); if (symbol_byte_size) @@ -4559,7 +4559,7 @@ ObjectFileMachO::ParseSymtab () else stub_symbol->SetType (eSymbolTypeResolver); stub_symbol->SetExternal (false); - stub_symbol->GetAddress() = so_addr; + stub_symbol->GetAddressRef() = so_addr; stub_symbol->SetByteSize (symbol_stub_byte_size); } else @@ -4578,7 +4578,7 @@ ObjectFileMachO::ParseSymtab () else sym[sym_idx].SetType (eSymbolTypeResolver); sym[sym_idx].SetIsSynthetic (true); - sym[sym_idx].GetAddress() = so_addr; + sym[sym_idx].GetAddressRef() = so_addr; sym[sym_idx].SetByteSize (symbol_stub_byte_size); ++sym_idx; } diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp index 5f7935e..8189f10 100644 --- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -574,7 +574,7 @@ ObjectFilePECOFF::GetSymtab() if ((int16_t)symbol.sect >= 1) { Address symbol_addr(sect_list->GetSectionAtIndex(symbol.sect-1), symbol.value); - symbols[i].GetAddress() = symbol_addr; + symbols[i].GetAddressRef() = symbol_addr; } if (symbol.naux > 0) @@ -633,7 +633,7 @@ ObjectFilePECOFF::GetSymtab() Address symbol_addr(m_coff_header_opt.image_base + function_rva, sect_list); symbols[i].GetMangled().SetValue(ConstString(symbol_name.c_str())); - symbols[i].GetAddress() = symbol_addr; + symbols[i].GetAddressRef() = symbol_addr; symbols[i].SetType(lldb::eSymbolTypeCode); symbols[i].SetDebug(true); } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index f487ae9..1671989 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -100,6 +100,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() : m_supports_QEnvironment (true), m_supports_QEnvironmentHexEncoded (true), m_supports_qSymbol (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), @@ -604,6 +605,32 @@ 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 () { @@ -4296,11 +4323,52 @@ GDBRemoteCommunicationClient::ServeSymbolLookups(lldb_private::Process *process) lldb_private::SymbolContextList sc_list; if (process->GetTarget().GetImages().FindSymbolsWithNameAndType(ConstString(symbol_name), eSymbolTypeAny, sc_list)) { - SymbolContext sc; - if (sc_list.GetContextAtIndex(0, sc)) + const size_t num_scs = sc_list.GetSize(); + for (size_t sc_idx=0; sc_idxGetAddress().GetLoadAddress(&process->GetTarget()); + SymbolContext sc; + if (sc_list.GetContextAtIndex(sc_idx, sc)) + { + if (sc.symbol) + { + switch (sc.symbol->GetType()) + { + case eSymbolTypeInvalid: + case eSymbolTypeAbsolute: + case eSymbolTypeUndefined: + case eSymbolTypeSourceFile: + case eSymbolTypeHeaderFile: + case eSymbolTypeObjectFile: + case eSymbolTypeCommonBlock: + case eSymbolTypeBlock: + case eSymbolTypeLocal: + case eSymbolTypeParam: + case eSymbolTypeVariable: + case eSymbolTypeVariableType: + case eSymbolTypeLineEntry: + case eSymbolTypeLineHeader: + case eSymbolTypeScopeBegin: + case eSymbolTypeScopeEnd: + case eSymbolTypeAdditional: + case eSymbolTypeCompiler: + case eSymbolTypeInstrumentation: + case eSymbolTypeTrampoline: + break; + + case eSymbolTypeCode: + case eSymbolTypeResolver: + case eSymbolTypeData: + case eSymbolTypeRuntime: + case eSymbolTypeException: + case eSymbolTypeObjCClass: + case eSymbolTypeObjCMetaClass: + case eSymbolTypeObjCIVar: + case eSymbolTypeReExported: + symbol_load_addr = sc.symbol->GetLoadAddress(&process->GetTarget()); + break; + } + } + } } } // This is the normal path where our symbol lookup was successful and we want diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 07a3bd9..28983b7 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -17,6 +17,7 @@ // 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" @@ -542,6 +543,9 @@ public: bool AvoidGPackets(ProcessGDBRemote *process); + StructuredData::ObjectSP + GetThreadsInfo(); + bool GetThreadExtendedInfoSupported(); @@ -624,7 +628,8 @@ protected: m_supports_z4:1, m_supports_QEnvironment:1, m_supports_QEnvironmentHexEncoded:1, - m_supports_qSymbol:1; + m_supports_qSymbol:1, + m_supports_jThreadsInfo: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 2b7ff24..a7e4d8c 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -378,6 +378,7 @@ 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 (), @@ -1795,6 +1796,362 @@ 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; iGetItemAtIndex(i)->GetAsDictionary(); + if (thread_dict) + { + if (thread_dict->GetValueForKeyAsInteger("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, + ExpeditedRegisterMap &expedited_register_map, + uint8_t signo, + const std::string &thread_name, + const std::string &reason, + const std::string &description, + uint32_t exc_type, + const std::vector &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 (thread_sp.get()); + gdb_thread->GetRegisterContext()->InvalidateIfNeeded(true); + + for (const auto &pair : expedited_register_map) + { + StringExtractor reg_value_extractor; + reg_value_extractor.GetStringRef() = pair.second; + gdb_thread->PrivateSetRegisterValue (pair.first, reg_value_extractor); + } + + // 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 exc_data; + addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS; + ExpeditedRegisterMap expedited_register_map; + // Iterate through all of the thread dictionary key/value pairs from the structured data dictionary + + thread_dict->ForEach([this, &tid, &expedited_register_map, &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) + { + StructuredData::Dictionary *registers_dict = object->GetAsDictionary(); + + if (registers_dict) + { + registers_dict->ForEach([&expedited_register_map](ConstString key, StructuredData::Object* object) -> bool { + const uint32_t reg = StringConvert::ToUInt32 (key.GetCString(), UINT32_MAX, 10); + if (reg != UINT32_MAX) + expedited_register_map[reg] = std::move(object->GetStringValue()); + return true; // Keep iterating through all array items + }); + } + } + 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("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 + }); + + SetThreadStopInfo (tid, + expedited_register_map, + signo, + thread_name, + reason, + description, + exc_type, + exc_data, + thread_dispatch_qaddr); + + return eStateExited; +} StateType ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) @@ -1825,8 +2182,9 @@ 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 name; + std::string key; std::string value; std::string thread_name; std::string reason; @@ -1838,48 +2196,25 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) std::string queue_name; QueueKind queue_kind = eQueueKindUnknown; uint64_t queue_serial = 0; - ThreadSP thread_sp; - ThreadGDBRemote *gdb_thread = NULL; - - while (stop_packet.GetNameColonValue(name, value)) + ExpeditedRegisterMap expedited_register_map; + while (stop_packet.GetNameColonValue(key, value)) { - if (name.compare("metype") == 0) + if (key.compare("metype") == 0) { // exception type in big endian hex exc_type = StringConvert::ToUInt32 (value.c_str(), 0, 16); } - else if (name.compare("medata") == 0) + else if (key.compare("medata") == 0) { // exception data in big endian hex exc_data.push_back(StringConvert::ToUInt64 (value.c_str(), 0, 16)); } - else if (name.compare("thread") == 0) + else if (key.compare("thread") == 0) { // thread in big endian hex - 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(thread_sp.get()), - thread_sp->GetID()); - - m_thread_list_real.AddThread(thread_sp); - } - gdb_thread = static_cast (thread_sp.get()); - + tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); } - else if (name.compare("threads") == 0) + else if (key.compare("threads") == 0) { Mutex::Locker locker(m_thread_list_real.GetMutex()); m_thread_ids.clear(); @@ -1901,7 +2236,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) if (tid != LLDB_INVALID_THREAD_ID) m_thread_ids.push_back (tid); } - else if (name.compare("hexname") == 0) + else if (key.compare("hexname") == 0) { StringExtractor name_extractor; // Swap "value" over into "name_extractor" @@ -1910,15 +2245,15 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) name_extractor.GetHexByteString (value); thread_name.swap (value); } - else if (name.compare("name") == 0) + else if (key.compare("name") == 0) { thread_name.swap (value); } - else if (name.compare("qaddr") == 0) + else if (key.compare("qaddr") == 0) { thread_dispatch_qaddr = StringConvert::ToUInt64 (value.c_str(), 0, 16); } - else if (name.compare("qname") == 0) + else if (key.compare("qname") == 0) { queue_vars_valid = true; StringExtractor name_extractor; @@ -1928,7 +2263,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) name_extractor.GetHexByteString (value); queue_name.swap (value); } - else if (name.compare("qkind") == 0) + else if (key.compare("qkind") == 0) { queue_vars_valid = true; if (value == "serial") @@ -1936,16 +2271,16 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) else if (value == "concurrent") queue_kind = eQueueKindConcurrent; } - else if (name.compare("qserial") == 0) + else if (key.compare("qserial") == 0) { queue_vars_valid = true; queue_serial = StringConvert::ToUInt64 (value.c_str(), 0, 0); } - else if (name.compare("reason") == 0) + else if (key.compare("reason") == 0) { reason.swap(value); } - else if (name.compare("description") == 0) + else if (key.compare("description") == 0) { StringExtractor desc_extractor; // Swap "value" over into "name_extractor" @@ -1954,34 +2289,57 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) desc_extractor.GetHexByteString (value); description.swap(value); } - else if (name.size() == 2 && ::isxdigit(name[0]) && ::isxdigit(name[1])) + else if (key.compare("memory") == 0) { - // 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) + // 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:=; + // 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 + // is native endian ASCII hex bytes just like the register values + llvm::StringRef value_ref(value); + std::pair pair; + pair = value_ref.split('='); + if (!pair.first.empty() && !pair.second.empty()) { - uint32_t reg = StringConvert::ToUInt32 (name.c_str(), UINT32_MAX, 16); - - if (reg != UINT32_MAX) + 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) { - 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()); - } + 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); } } } + 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, + expedited_register_map, + 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) @@ -1992,164 +2350,9 @@ 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 (thread_sp.get ()); } } - if (thread_sp) - { - // Clear the stop info just in case we don't set it to anything - thread_sp->SetStopInfo (StopInfoSP()); - - gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr); - if (queue_vars_valid) - gdb_thread->SetQueueInfo(std::move(queue_name), queue_kind, queue_serial); - else - gdb_thread->ClearQueueInfo(); - - 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 - { - 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 eStateStopped; } break; @@ -2206,6 +2409,11 @@ 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 16e47df..d810d9c 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -326,6 +326,9 @@ protected: void GetMaxMemorySize(); + bool + CalculateThreadStopInfo (ThreadGDBRemote *thread); + //------------------------------------------------------------------ /// Broadcaster event bits definitions. //------------------------------------------------------------------ @@ -348,7 +351,9 @@ protected: typedef std::vector tid_collection; typedef std::vector< std::pair > tid_sig_collection; typedef std::map MMapMap; + typedef std::map ExpeditedRegisterMap; 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 @@ -385,6 +390,20 @@ protected: lldb::StateType SetThreadStopInfo (StringExtractor& stop_packet); + lldb::StateType + SetThreadStopInfo (StructuredData::Dictionary *thread_dict); + + lldb::ThreadSP + SetThreadStopInfo (lldb::tid_t tid, + ExpeditedRegisterMap &expedited_register_map, + uint8_t signo, + const std::string &thread_name, + const std::string &reason, + const std::string &description, + uint32_t exc_type, + const std::vector &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 e58121b..59c701d 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -317,12 +317,7 @@ ThreadGDBRemote::CalculateStopInfo () { ProcessSP process_sp (GetProcess()); if (process_sp) - { - StringExtractorGDBRemote stop_packet; - ProcessGDBRemote *gdb_process = static_cast(process_sp.get()); - if (gdb_process->GetGDBRemote().GetThreadStopInfo(GetProtocolID(), stop_packet)) - return gdb_process->SetThreadStopInfo (stop_packet) == eStateStopped; - } + return static_cast(process_sp.get())->CalculateThreadStopInfo(this); return false; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 4d3d22a..dafd389 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -7620,7 +7620,7 @@ SymbolFileDWARF::ParseVariableDIE { if (exe_symbol->ValueIsAddress()) { - const addr_t exe_file_addr = exe_symbol->GetAddress().GetFileAddress(); + const addr_t exe_file_addr = exe_symbol->GetAddressRef().GetFileAddress(); if (exe_file_addr != LLDB_INVALID_ADDRESS) { if (location.Update_DW_OP_addr (exe_file_addr)) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index d5d60ae..5579a23 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -121,8 +121,8 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa { // Add the inverse OSO file address to debug map entry mapping exe_symfile->AddOSOFileRange (this, - exe_symbol->GetAddress().GetFileAddress(), - oso_fun_symbol->GetAddress().GetFileAddress(), + exe_symbol->GetAddressRef().GetFileAddress(), + oso_fun_symbol->GetAddressRef().GetFileAddress(), std::min(exe_symbol->GetByteSize(), oso_fun_symbol->GetByteSize())); } @@ -155,8 +155,8 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa { // Add the inverse OSO file address to debug map entry mapping exe_symfile->AddOSOFileRange (this, - exe_symbol->GetAddress().GetFileAddress(), - oso_gsym_symbol->GetAddress().GetFileAddress(), + exe_symbol->GetAddressRef().GetFileAddress(), + oso_gsym_symbol->GetAddressRef().GetFileAddress(), std::min(exe_symbol->GetByteSize(), oso_gsym_symbol->GetByteSize())); } } @@ -374,7 +374,7 @@ SymbolFileDWARFDebugMap::InitOSO() for (uint32_t sym_idx : m_func_indexes) { const Symbol *symbol = symtab->SymbolAtIndex(sym_idx); - lldb::addr_t file_addr = symbol->GetAddress().GetFileAddress(); + lldb::addr_t file_addr = symbol->GetAddressRef().GetFileAddress(); lldb::addr_t byte_size = symbol->GetByteSize(); DebugMap::Entry debug_map_entry(file_addr, byte_size, OSOEntry(sym_idx, LLDB_INVALID_ADDRESS)); m_debug_map.Append(debug_map_entry); @@ -382,7 +382,7 @@ SymbolFileDWARFDebugMap::InitOSO() for (uint32_t sym_idx : m_glob_indexes) { const Symbol *symbol = symtab->SymbolAtIndex(sym_idx); - lldb::addr_t file_addr = symbol->GetAddress().GetFileAddress(); + lldb::addr_t file_addr = symbol->GetAddressRef().GetFileAddress(); lldb::addr_t byte_size = symbol->GetByteSize(); DebugMap::Entry debug_map_entry(file_addr, byte_size, OSOEntry(sym_idx, LLDB_INVALID_ADDRESS)); m_debug_map.Append(debug_map_entry); @@ -405,7 +405,7 @@ SymbolFileDWARFDebugMap::InitOSO() m_compile_unit_infos[i].so_file.SetFile(so_symbol->GetName().AsCString(), false); m_compile_unit_infos[i].oso_path = oso_symbol->GetName(); TimeValue oso_mod_time; - oso_mod_time.OffsetWithSeconds(oso_symbol->GetAddress().GetOffset()); + oso_mod_time.OffsetWithSeconds(oso_symbol->GetIntegerValue(0)); m_compile_unit_infos[i].oso_mod_time = oso_mod_time; uint32_t sibling_idx = so_symbol->GetSiblingIndex(); // The sibling index can't be less that or equal to the current index "i" diff --git a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp index 8eb3e3a..64c88ab 100644 --- a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp +++ b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp @@ -225,7 +225,7 @@ SymbolFileSymtab::ParseCompileUnitFunctions (const SymbolContext &sc) next_symbol = symtab->SymbolAtIndex(m_code_indexes[idx + 1]); if (next_symbol) { - func_range.SetByteSize(next_symbol->GetAddress().GetOffset() - curr_symbol->GetAddress().GetOffset()); + func_range.SetByteSize(next_symbol->GetAddressRef().GetOffset() - curr_symbol->GetAddressRef().GetOffset()); } } diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp index 9b18ead..67f9c59 100644 --- a/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp @@ -316,7 +316,7 @@ SystemRuntimeMacOSX::ReadLibdispatchOffsetsAddress () dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData); } if (dispatch_queue_offsets_symbol) - m_dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetAddress().GetLoadAddress(&m_process->GetTarget()); + m_dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetLoadAddress(&m_process->GetTarget()); } void @@ -361,7 +361,7 @@ SystemRuntimeMacOSX::ReadLibpthreadOffsetsAddress () (g_libpthread_layout_offsets_symbol_name, eSymbolTypeData); if (libpthread_layout_offsets_symbol) { - m_libpthread_layout_offsets_addr = libpthread_layout_offsets_symbol->GetAddress().GetLoadAddress(&m_process->GetTarget()); + m_libpthread_layout_offsets_addr = libpthread_layout_offsets_symbol->GetLoadAddress(&m_process->GetTarget()); } } } @@ -410,7 +410,7 @@ SystemRuntimeMacOSX::ReadLibdispatchTSDIndexesAddress () (g_libdispatch_tsd_indexes_symbol_name, eSymbolTypeData); if (libdispatch_tsd_indexes_symbol) { - m_dispatch_tsd_indexes_addr = libdispatch_tsd_indexes_symbol->GetAddress().GetLoadAddress(&m_process->GetTarget()); + m_dispatch_tsd_indexes_addr = libdispatch_tsd_indexes_symbol->GetLoadAddress(&m_process->GetTarget()); } } } diff --git a/lldb/source/Symbol/ObjectFile.cpp b/lldb/source/Symbol/ObjectFile.cpp index b860bcf..22a313c 100644 --- a/lldb/source/Symbol/ObjectFile.cpp +++ b/lldb/source/Symbol/ObjectFile.cpp @@ -328,7 +328,7 @@ ObjectFile::GetAddressClass (addr_t file_addr) { if (symbol->ValueIsAddress()) { - const SectionSP section_sp (symbol->GetAddress().GetSection()); + const SectionSP section_sp (symbol->GetAddressRef().GetSection()); if (section_sp) { const SectionType section_type = section_sp->GetType(); diff --git a/lldb/source/Symbol/Symbol.cpp b/lldb/source/Symbol/Symbol.cpp index 4a1ae81..dff15dd 100644 --- a/lldb/source/Symbol/Symbol.cpp +++ b/lldb/source/Symbol/Symbol.cpp @@ -491,7 +491,7 @@ Symbol::CalculateSymbolContext (SymbolContext *sc) // Symbols can reconstruct the symbol and the module in the symbol context sc->symbol = this; if (ValueIsAddress()) - sc->module_sp = GetAddress().GetModule(); + sc->module_sp = GetAddressRef().GetModule(); else sc->module_sp.reset(); } @@ -500,7 +500,7 @@ ModuleSP Symbol::CalculateSymbolContextModule () { if (ValueIsAddress()) - return GetAddress().GetModule(); + return GetAddressRef().GetModule(); return ModuleSP(); } @@ -516,7 +516,7 @@ Symbol::DumpSymbolContext (Stream *s) bool dumped_module = false; if (ValueIsAddress()) { - ModuleSP module_sp (GetAddress().GetModule()); + ModuleSP module_sp (GetAddressRef().GetModule()); if (module_sp) { dumped_module = true; @@ -618,6 +618,25 @@ Symbol::ResolveReExportedSymbol (Target &target) const } lldb::addr_t +Symbol::GetFileAddress () const +{ + if (ValueIsAddress()) + return GetAddressRef().GetFileAddress(); + else + return LLDB_INVALID_ADDRESS; +} + +lldb::addr_t +Symbol::GetLoadAddress (Target *target) const +{ + if (ValueIsAddress()) + return GetAddressRef().GetLoadAddress(target); + else + return LLDB_INVALID_ADDRESS; +} + + +lldb::addr_t Symbol::ResolveCallableAddress(Target &target) const { if (GetType() == lldb::eSymbolTypeUndefined) diff --git a/lldb/source/Symbol/SymbolContext.cpp b/lldb/source/Symbol/SymbolContext.cpp index d65462b..8e4240a4 100644 --- a/lldb/source/Symbol/SymbolContext.cpp +++ b/lldb/source/Symbol/SymbolContext.cpp @@ -245,7 +245,7 @@ SymbolContext::DumpStopContext ( if (addr.IsValid() && symbol->ValueIsAddress()) { - const addr_t symbol_offset = addr.GetOffset() - symbol->GetAddress().GetOffset(); + const addr_t symbol_offset = addr.GetOffset() - symbol->GetAddressRef().GetOffset(); if (show_function_name == false) { // Print +offset even if offset is 0 @@ -515,7 +515,7 @@ SymbolContext::GetAddressRange (uint32_t scope, { if (symbol->ValueIsAddress()) { - range.GetBaseAddress() = symbol->GetAddress(); + range.GetBaseAddress() = symbol->GetAddressRef(); range.SetByteSize (symbol->GetByteSize()); return true; } @@ -1106,7 +1106,7 @@ SymbolContextList::AppendIfUnique (const SymbolContext& sc, bool merge_symbol_in if (pos->function) { - if (pos->function->GetAddressRange().GetBaseAddress() == sc.symbol->GetAddress()) + if (pos->function->GetAddressRange().GetBaseAddress() == sc.symbol->GetAddressRef()) { // Do we already have a function with this symbol? if (pos->symbol == sc.symbol) @@ -1148,7 +1148,7 @@ SymbolContextList::MergeSymbolContextIntoFunctionContext (const SymbolContext& s if (function_sc.function) { - if (function_sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddress()) + if (function_sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRef()) { // Do we already have a function with this symbol? if (function_sc.symbol == symbol_sc.symbol) diff --git a/lldb/source/Symbol/Symtab.cpp b/lldb/source/Symbol/Symtab.cpp index dc69525..4cc0334 100644 --- a/lldb/source/Symbol/Symtab.cpp +++ b/lldb/source/Symbol/Symtab.cpp @@ -598,14 +598,14 @@ namespace { addr_t value_a = addr_cache[index_a]; if (value_a == LLDB_INVALID_ADDRESS) { - value_a = symbols[index_a].GetAddress().GetFileAddress(); + value_a = symbols[index_a].GetAddressRef().GetFileAddress(); addr_cache[index_a] = value_a; } addr_t value_b = addr_cache[index_b]; if (value_b == LLDB_INVALID_ADDRESS) { - value_b = symbols[index_b].GetAddress().GetFileAddress(); + value_b = symbols[index_b].GetAddressRef().GetFileAddress(); addr_cache[index_b] = value_b; } @@ -902,7 +902,7 @@ SymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr) const addr_t info_file_addr = info->file_addr; if (symbol->ValueIsAddress()) { - const addr_t curr_file_addr = symbol->GetAddress().GetFileAddress(); + const addr_t curr_file_addr = symbol->GetAddressRef().GetFileAddress(); if (info_file_addr < curr_file_addr) return -1; @@ -936,7 +936,7 @@ Symtab::InitAddressIndexes() { if (pos->ValueIsAddress()) { - entry.SetRangeBase(pos->GetAddress().GetFileAddress()); + entry.SetRangeBase(pos->GetAddressRef().GetFileAddress()); entry.SetByteSize(pos->GetByteSize()); entry.data = std::distance(begin, pos); m_file_addr_to_index.Append(entry); diff --git a/lldb/source/Target/Memory.cpp b/lldb/source/Target/Memory.cpp index 934bc96..e61b3ab 100644 --- a/lldb/source/Target/Memory.cpp +++ b/lldb/source/Target/Memory.cpp @@ -14,8 +14,9 @@ // Other libraries and framework includes // Project includes #include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/State.h" #include "lldb/Core/Log.h" +#include "lldb/Core/RangeMap.h" +#include "lldb/Core/State.h" #include "lldb/Target/Process.h" using namespace lldb; @@ -25,11 +26,12 @@ using namespace lldb_private; // MemoryCache constructor //---------------------------------------------------------------------- MemoryCache::MemoryCache(Process &process) : - m_process (process), - m_cache_line_byte_size (process.GetMemoryCacheLineSize()), m_mutex (Mutex::eMutexTypeRecursive), - m_cache (), - m_invalid_ranges () + m_L1_cache (), + m_L2_cache (), + m_invalid_ranges (), + m_process (process), + m_L2_cache_line_byte_size (process.GetMemoryCacheLineSize()) { } @@ -44,10 +46,24 @@ void MemoryCache::Clear(bool clear_invalid_ranges) { Mutex::Locker locker (m_mutex); - m_cache.clear(); + m_L1_cache.clear(); + m_L2_cache.clear(); if (clear_invalid_ranges) m_invalid_ranges.Clear(); - m_cache_line_byte_size = m_process.GetMemoryCacheLineSize(); + 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; } void @@ -57,29 +73,44 @@ MemoryCache::Flush (addr_t addr, size_t size) return; Mutex::Locker locker (m_mutex); - if (m_cache.empty()) - return; - 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) + // Erase any blocks from the L1 cache that intersect with the flush range + if (!m_L1_cache.empty()) { - BlockMap::iterator pos = m_cache.find (curr_addr); - if (pos != m_cache.end()) - m_cache.erase(pos); + 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); + } } } @@ -122,6 +153,39 @@ 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 @@ -129,19 +193,22 @@ 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_cache_line_byte_size) + if (dst && dst_len > m_L2_cache_line_byte_size) { - return m_process.ReadMemoryFromInferior (addr, dst, dst_len, error); + 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; } if (dst && bytes_left > 0) { - const uint32_t cache_line_byte_size = m_cache_line_byte_size; + const uint32_t cache_line_byte_size = m_L2_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)) @@ -150,8 +217,8 @@ MemoryCache::Read (addr_t addr, return dst_len - bytes_left; } - BlockMap::const_iterator pos = m_cache.find (curr_addr); - BlockMap::const_iterator end = m_cache.end (); + BlockMap::const_iterator pos = m_L2_cache.find (curr_addr); + BlockMap::const_iterator end = m_L2_cache.end (); if (pos != end) { @@ -208,7 +275,7 @@ MemoryCache::Read (addr_t addr, if (process_bytes_read != cache_line_byte_size) data_buffer_heap_ap->SetByteSize (process_bytes_read); - m_cache[curr_addr] = DataBufferSP (data_buffer_heap_ap.release()); + m_L2_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/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 77e9b5d..4194282 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -2246,11 +2246,12 @@ Process::CreateBreakpointSite (const BreakpointLocationSP &owner, bool use_hardw if (symbol && symbol->IsIndirect()) { Error error; - load_addr = ResolveIndirectFunction (&symbol->GetAddress(), error); + Address symbol_address = symbol->GetAddress(); + load_addr = ResolveIndirectFunction (&symbol_address, error); if (!error.Success() && show_error) { m_target.GetDebugger().GetErrorFile()->Printf ("warning: failed to resolve indirect function at 0x%" PRIx64 " for breakpoint %i.%i: %s\n", - symbol->GetAddress().GetLoadAddress(&m_target), + symbol->GetLoadAddress(&m_target), owner->GetBreakpoint().GetID(), owner->GetID(), error.AsCString() ? error.AsCString() : "unknown error"); diff --git a/lldb/source/Target/ThreadPlanStepRange.cpp b/lldb/source/Target/ThreadPlanStepRange.cpp index 324f5a7..3aed858 100644 --- a/lldb/source/Target/ThreadPlanStepRange.cpp +++ b/lldb/source/Target/ThreadPlanStepRange.cpp @@ -243,9 +243,9 @@ ThreadPlanStepRange::InSymbol() { return m_addr_context.function->GetAddressRange().ContainsLoadAddress (cur_pc, m_thread.CalculateTarget().get()); } - else if (m_addr_context.symbol) + else if (m_addr_context.symbol && m_addr_context.symbol->ValueIsAddress()) { - AddressRange range(m_addr_context.symbol->GetAddress(), m_addr_context.symbol->GetByteSize()); + AddressRange range(m_addr_context.symbol->GetAddressRef(), m_addr_context.symbol->GetByteSize()); return range.ContainsLoadAddress (cur_pc, m_thread.CalculateTarget().get()); } return false; diff --git a/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj b/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj index f7cbc13..c824212 100644 --- a/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj +++ b/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj @@ -55,6 +55,7 @@ 26203D1D1641EFB200A662F7 /* com.apple.debugserver.internal.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.debugserver.internal.plist; sourceTree = ""; }; 26242C390DDBD33C0054A4CC /* debugserver-entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "debugserver-entitlements.plist"; sourceTree = ""; }; 264D5D571293835600ED4C01 /* DNBArch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DNBArch.cpp; sourceTree = ""; }; + 264F679A1B2F9EB200140093 /* JSONGenerator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSONGenerator.h; sourceTree = ""; }; 26593A060D4931CC001C9FE3 /* ChangeLog */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ChangeLog; sourceTree = ""; }; 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; }; @@ -232,6 +233,7 @@ 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/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp index 1ddf902..7498f2e 100644 --- a/lldb/tools/debugserver/source/RNBRemote.cpp +++ b/lldb/tools/debugserver/source/RNBRemote.cpp @@ -29,6 +29,7 @@ #include "DNBDataRef.h" #include "DNBLog.h" #include "DNBThreadResumeActions.h" +#include "JSONGenerator.h" #include "RNBContext.h" #include "RNBServices.h" #include "RNBSocket.h" @@ -262,6 +263,7 @@ 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_qSymbol , 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")); @@ -2559,6 +2561,52 @@ RNBRemote::DispatchQueueOffsets::GetThreadQueueInfo (nub_process_t pid, } } +struct StackMemory +{ + uint8_t bytes[2*sizeof(nub_addr_t)]; + nub_size_t length; +}; +typedef std::map 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) { @@ -2714,11 +2762,26 @@ 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"); @@ -4898,11 +4961,136 @@ 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; iAddItem(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()) { @@ -5132,8 +5320,7 @@ RNBRemote::HandlePacket_jThreadExtendedInfo (const char *p) json << "}"; std::string json_quoted = binary_encode_string (json.str()); - reply_strm << json_quoted; - return SendPacket (reply_strm.str()); + return SendPacket (json_quoted); } } return SendPacket ("OK"); diff --git a/lldb/tools/debugserver/source/RNBRemote.h b/lldb/tools/debugserver/source/RNBRemote.h index 3fcccc2..00cfe79 100644 --- a/lldb/tools/debugserver/source/RNBRemote.h +++ b/lldb/tools/debugserver/source/RNBRemote.h @@ -103,6 +103,7 @@ 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 @@ -190,6 +191,7 @@ 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); -- 2.7.4